From 825f053e069f1cbb7bc8616693b65e3a98466ec3 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 14 Mar 2024 05:17:54 +0100 Subject: [PATCH] JIT: inline shared generics with runtime lookups inside (#99265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakob Botsch Nielsen Co-authored-by: Michal Strehovský --- src/coreclr/inc/corinfo.h | 4 + src/coreclr/inc/icorjitinfoimpl_generated.h | 4 + src/coreclr/inc/jiteeversionguid.h | 10 +- .../jit/ICorJitInfo_wrapper_generated.hpp | 12 +- src/coreclr/jit/compiler.h | 10 +- src/coreclr/jit/compiler.hpp | 6 +- src/coreclr/jit/fginline.cpp | 366 +++++++++--------- src/coreclr/jit/flowgraph.cpp | 7 +- src/coreclr/jit/gentree.cpp | 6 +- src/coreclr/jit/importer.cpp | 112 ++++-- src/coreclr/jit/importercalls.cpp | 2 +- src/coreclr/jit/inline.h | 1 + src/coreclr/jit/jiteh.cpp | 4 +- src/coreclr/jit/lclvars.cpp | 12 +- src/coreclr/jit/morph.cpp | 12 +- .../JitInterface/CorInfoImpl_generated.cs | 24 +- .../ThunkGenerator/ThunkInput.txt | 8 +- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 34 +- .../JitInterface/CorInfoImpl.RyuJit.cs | 147 ++++--- .../aot/jitinterface/jitinterface_generated.h | 20 +- .../tools/superpmi/superpmi-shared/agnostic.h | 9 + .../tools/superpmi/superpmi-shared/lwmlist.h | 2 +- .../superpmi-shared/methodcontext.cpp | 32 +- .../superpmi/superpmi-shared/methodcontext.h | 12 +- .../superpmi-shim-collector/icorjitinfo.cpp | 20 +- .../icorjitinfo_generated.cpp | 12 +- .../icorjitinfo_generated.cpp | 12 +- .../tools/superpmi/superpmi/icorjitinfo.cpp | 13 +- src/coreclr/vm/jitinterface.cpp | 39 +- src/coreclr/vm/jitinterface.h | 1 + 30 files changed, 522 insertions(+), 431 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 963793057bfc17..b9ebaa08546014 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2231,6 +2231,7 @@ class ICorStaticInfo // should be looked up at runtime. virtual void expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT * pResult) = 0; // Is the given type in System.Private.Corelib and marked with IntrinsicAttribute? @@ -2647,6 +2648,7 @@ class ICorStaticInfo CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP * pLookup ) = 0; @@ -2654,6 +2656,7 @@ class ICorStaticInfo CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP * pLookup ) = 0; @@ -3193,6 +3196,7 @@ class ICorDynamicInfo : public ICorStaticInfo virtual void embedGenericHandle( CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fEmbedParent, // `true` - embeds parent type handle of the field/method handle + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT * pResult ) = 0; diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 51dc4e8388e575..2348162d948545 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -104,6 +104,7 @@ CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass( void expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) override; bool isIntrinsicType( @@ -297,12 +298,14 @@ bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) override; void getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) override; CorInfoInitClassResult initClass( @@ -560,6 +563,7 @@ CORINFO_FIELD_HANDLE embedFieldHandle( void embedGenericHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) override; void getLocationOfThisType( diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index b6cc5d7a0b4757..9022ceff18bc54 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 = { /* e5f629d4-edc8-48f1-a75d-0fa1f0b5af6f */ - 0xe5f629d4, - 0xedc8, - 0x48f1, - {0xa7, 0x5d, 0x0f, 0xa1, 0xf0, 0xb5, 0xaf, 0x6f} +constexpr GUID JITEEVersionIdentifier = { /* 35afdf61-5417-4bd7-9302-48efa2507603 */ + 0x35afdf61, + 0x5417, + 0x4bd7, + {0x93, 0x02, 0x48, 0xef, 0xa2, 0x50, 0x76, 0x03} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 8a9487ad96f696..77af720739ecee 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -202,10 +202,11 @@ CORINFO_CLASS_HANDLE WrapICorJitInfo::getDefaultEqualityComparerClass( void WrapICorJitInfo::expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { API_ENTER(expandRawHandleIntrinsic); - wrapHnd->expandRawHandleIntrinsic(pResolvedToken, pResult); + wrapHnd->expandRawHandleIntrinsic(pResolvedToken, callerHandle, pResult); API_LEAVE(expandRawHandleIntrinsic); } @@ -687,10 +688,11 @@ bool WrapICorJitInfo::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { API_ENTER(getReadyToRunHelper); - bool temp = wrapHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup); + bool temp = wrapHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup); API_LEAVE(getReadyToRunHelper); return temp; } @@ -699,10 +701,11 @@ void WrapICorJitInfo::getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { API_ENTER(getReadyToRunDelegateCtorHelper); - wrapHnd->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, pLookup); + wrapHnd->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); API_LEAVE(getReadyToRunDelegateCtorHelper); } @@ -1330,10 +1333,11 @@ CORINFO_FIELD_HANDLE WrapICorJitInfo::embedFieldHandle( void WrapICorJitInfo::embedGenericHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { API_ENTER(embedGenericHandle); - wrapHnd->embedGenericHandle(pResolvedToken, fEmbedParent, pResult); + wrapHnd->embedGenericHandle(pResolvedToken, fEmbedParent, callerHandle, pResult); API_LEAVE(embedGenericHandle); } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 5b18ebaeabae33..08a8148f780ea0 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3440,7 +3440,7 @@ class Compiler GenTreeAllocObj* gtNewAllocObjNode( unsigned int helper, bool helperHasSideEffects, CORINFO_CLASS_HANDLE clsHnd, var_types type, GenTree* op1); - GenTreeAllocObj* gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool useParent); + GenTreeAllocObj* gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, bool useParent); GenTree* gtNewRuntimeLookup(CORINFO_GENERIC_HANDLE hnd, CorInfoGenericHandleType hndTyp, GenTree* lookupTree); @@ -4923,7 +4923,7 @@ class Compiler unsigned impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reason)); - GenTree* impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, InlLclVarInfo* lclTypeInfo); + GenTree* impInlineFetchArg(InlArgInfo& argInfo, const InlLclVarInfo& lclInfo); bool impInlineIsThis(GenTree* tree, InlArgInfo* inlArgInfo); @@ -6629,6 +6629,7 @@ class Compiler void fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* result, InlineContext** createdContext); void fgInsertInlineeBlocks(InlineInfo* pInlineInfo); + void fgInsertInlineeArgument(const InlArgInfo& argInfo, BasicBlock* block, Statement** afterStmt, Statement** newStmt, const DebugInfo& callDI); Statement* fgInlinePrependStatements(InlineInfo* inlineInfo); void fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, Statement* stmt); @@ -10217,8 +10218,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX unsigned compArgStackSize; // Incoming argument stack size in bytes #endif // FEATURE_FASTTAILCALL - unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present); - int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE) + unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present); + unsigned compTypeCtxtArg; // position of hidden param for type context for generic code + // (CORINFO_CALLCONV_PARAMTYPE) unsigned compThisArg; // position of implicit this pointer param (not to be confused with lvaArg0Var) unsigned compILlocalsCount; // Number of vars : args + locals (incl. implicit but not hidden) unsigned compLocalsCount; // Number of vars : args + locals (incl. implicit and hidden) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 2e157bf7eab489..359adc030f8083 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -2443,7 +2443,7 @@ inline bool Compiler::lvaReportParamTypeArg() { if (info.compMethodInfo->options & (CORINFO_GENERICS_CTXT_FROM_METHODDESC | CORINFO_GENERICS_CTXT_FROM_METHODTABLE)) { - assert(info.compTypeCtxtArg != -1); + assert(info.compTypeCtxtArg != BAD_VAR_NUM); // If the VM requires us to keep the generics context alive and report it (for example, if any catch // clause catches a type that uses a generic parameter of this method) this flag will be set. @@ -2773,13 +2773,13 @@ inline unsigned Compiler::compMapILargNum(unsigned ILargNum) assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } - if (ILargNum >= (unsigned)info.compTypeCtxtArg) + if (ILargNum >= info.compTypeCtxtArg) { ILargNum++; assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } - if (ILargNum >= (unsigned)lvaVarargsHandleArg) + if (ILargNum >= lvaVarargsHandleArg) { ILargNum++; assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 5267cdebfd0f80..b72b99228fbc70 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -1177,6 +1177,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe inlineInfo.retExprClassHnd = nullptr; inlineInfo.retExprClassHndIsExact = false; inlineInfo.inlineResult = inlineResult; + inlineInfo.inlInstParamArgInfo = nullptr; #ifdef FEATURE_SIMD inlineInfo.hasSIMDTypeArgLocalOrReturn = false; #endif // FEATURE_SIMD @@ -1664,6 +1665,175 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) iciStmt->SetRootNode(gtNewNothingNode()); } +//------------------------------------------------------------------------ +// fgInsertInlineeArgument: wire up the given argument from the callsite with the inlinee +// +// Arguments: +// argInfo - information about the argument +// block - block to insert the argument into +// afterStmt - statement to insert the argument after +// newStmt - updated with the new statement +// callDI - debug info for the call +// +void Compiler::fgInsertInlineeArgument( + const InlArgInfo& argInfo, BasicBlock* block, Statement** afterStmt, Statement** newStmt, const DebugInfo& callDI) +{ + const bool argIsSingleDef = !argInfo.argHasLdargaOp && !argInfo.argHasStargOp; + CallArg* arg = argInfo.arg; + GenTree* argNode = arg->GetNode(); + + assert(!argNode->OperIs(GT_RET_EXPR)); + + if (argInfo.argHasTmp) + { + noway_assert(argInfo.argIsUsed); + + /* argBashTmpNode is non-NULL iff the argument's value was + referenced exactly once by the original IL. This offers an + opportunity to avoid an intermediate temp and just insert + the original argument tree. + + However, if the temp node has been cloned somewhere while + importing (e.g. when handling isinst or dup), or if the IL + took the address of the argument, then argBashTmpNode will + be set (because the value was only explicitly retrieved + once) but the optimization cannot be applied. + */ + + GenTree* argSingleUseNode = argInfo.argBashTmpNode; + + if ((argSingleUseNode != nullptr) && !(argSingleUseNode->gtFlags & GTF_VAR_MOREUSES) && argIsSingleDef) + { + // Change the temp in-place to the actual argument. + // We currently do not support this for struct arguments, so it must not be a GT_BLK. + assert(argNode->gtOper != GT_BLK); + argSingleUseNode->ReplaceWith(argNode, this); + return; + } + else + { + // We're going to assign the argument value to the temp we use for it in the inline body. + GenTree* store = gtNewTempStore(argInfo.argTmpNum, argNode); + + *newStmt = gtNewStmt(store, callDI); + fgInsertStmtAfter(block, *afterStmt, *newStmt); + *afterStmt = *newStmt; + DISPSTMT(*afterStmt); + } + } + else if (argInfo.argIsByRefToStructLocal) + { + // Do nothing. Arg was directly substituted as we read + // the inlinee. + } + else + { + // The argument is either not used or a const or lcl var + noway_assert(!argInfo.argIsUsed || argInfo.argIsInvariant || argInfo.argIsLclVar); + noway_assert((argInfo.argIsLclVar == 0) == + (argNode->gtOper != GT_LCL_VAR || (argNode->gtFlags & GTF_GLOB_REF))); + + // If the argument has side effects, append it + if (argInfo.argHasSideEff) + { + noway_assert(argInfo.argIsUsed == false); + *newStmt = nullptr; + bool append = true; + + if (argNode->gtOper == GT_BLK || argNode->gtOper == GT_MKREFANY) + { + // Don't put GT_BLK node under a GT_COMMA. + // Codegen can't deal with it. + // Just hang the address here in case there are side-effect. + *newStmt = gtNewStmt(gtUnusedValNode(argNode->AsOp()->gtOp1), callDI); + } + else + { + // In some special cases, unused args with side effects can + // trigger further changes. + // + // (1) If the arg is a static field access and the field access + // was produced by a call to EqualityComparer.get_Default, the + // helper call to ensure the field has a value can be suppressed. + // This helper call is marked as a "Special DCE" helper during + // importation, over in fgGetStaticsCCtorHelper. + // + // (2) NYI. If we find that the actual arg expression + // has no side effects, we can skip appending all + // together. This will help jit TP a bit. + // + assert(!argNode->OperIs(GT_RET_EXPR)); + + // For case (1) + // + // Look for the following tree shapes + // prejit: (IND (ADD (CONST, CALL(special dce helper...)))) + // jit : (COMMA (CALL(special dce helper...), (FIELD ...))) + if (argNode->gtOper == GT_COMMA) + { + // Look for (COMMA (CALL(special dce helper...), (FIELD ...))) + GenTree* op1 = argNode->AsOp()->gtOp1; + GenTree* op2 = argNode->AsOp()->gtOp2; + if (op1->IsCall() && ((op1->AsCall()->gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) && + op2->OperIs(GT_IND) && op2->gtGetOp1()->IsIconHandle() && ((op2->gtFlags & GTF_EXCEPT) == 0)) + { + JITDUMP("\nPerforming special dce on unused arg [%06u]:" + " actual arg [%06u] helper call [%06u]\n", + argNode->gtTreeID, argNode->gtTreeID, op1->gtTreeID); + // Drop the whole tree + append = false; + } + } + else if (argNode->gtOper == GT_IND) + { + // Look for (IND (ADD (CONST, CALL(special dce helper...)))) + GenTree* addr = argNode->AsOp()->gtOp1; + + if (addr->gtOper == GT_ADD) + { + GenTree* op1 = addr->AsOp()->gtOp1; + GenTree* op2 = addr->AsOp()->gtOp2; + if (op1->IsCall() && ((op1->AsCall()->gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) && + op2->IsCnsIntOrI()) + { + // Drop the whole tree + JITDUMP("\nPerforming special dce on unused arg [%06u]:" + " actual arg [%06u] helper call [%06u]\n", + argNode->gtTreeID, argNode->gtTreeID, op1->gtTreeID); + append = false; + } + } + } + } + + if (!append) + { + assert(*newStmt == nullptr); + JITDUMP("Arg tree side effects were discardable, not appending anything for arg\n"); + } + else + { + // If we don't have something custom to append, + // just append the arg node as an unused value. + if (*newStmt == nullptr) + { + *newStmt = gtNewStmt(gtUnusedValNode(argNode), callDI); + } + + fgInsertStmtAfter(block, *afterStmt, *newStmt); + *afterStmt = *newStmt; + DISPSTMT(*afterStmt); + } + } + else if (argNode->IsBoxedValue()) + { + // Try to clean up any unnecessary boxing side effects + // since the box itself will be ignored. + gtTryRemoveBoxUpstreamEffects(argNode); + } + } +} + //------------------------------------------------------------------------ // fgInlinePrependStatements: prepend statements needed to match up // caller and inlined callee @@ -1685,28 +1855,18 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // Newly added statements are placed just after the original call // and are are given the same inline context as the call any calls // added here will appear to have been part of the immediate caller. - +// Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) { BasicBlock* block = inlineInfo->iciBlock; Statement* callStmt = inlineInfo->iciStmt; const DebugInfo& callDI = callStmt->GetDebugInfo(); - Statement* postStmt = callStmt->GetNextStmt(); Statement* afterStmt = callStmt; // afterStmt is the place where the new statements should be inserted after. Statement* newStmt = nullptr; GenTreeCall* call = inlineInfo->iciCall->AsCall(); noway_assert(call->gtOper == GT_CALL); -#ifdef DEBUG - if (0 && verbose) - { - printf("\nfgInlinePrependStatements for iciCall= "); - printTreeID(call); - printf(":\n"); - } -#endif - // Prepend statements for any initialization / side effects InlArgInfo* inlArgInfo = inlineInfo->inlArgInfo; @@ -1727,7 +1887,7 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst) { // Call impInlineFetchArg to "reserve" a temp for the "this" pointer. - GenTree* thisOp = impInlineFetchArg(0, inlArgInfo, lclVarInfo); + GenTree* thisOp = impInlineFetchArg(inlArgInfo[0], lclVarInfo[0]); if (fgAddrCouldBeNull(thisOp)) { nullcheck = gtNewNullCheck(thisOp, block); @@ -1736,183 +1896,19 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) } } - /* Treat arguments that had to be assigned to temps */ - if (inlineInfo->argCnt) + // Append the InstParam + if (inlineInfo->inlInstParamArgInfo != nullptr) { + fgInsertInlineeArgument(*inlineInfo->inlInstParamArgInfo, block, &afterStmt, &newStmt, callDI); + } -#ifdef DEBUG - if (verbose) - { - printf("\nArguments setup:\n"); - } -#endif // DEBUG - + // Treat arguments that had to be assigned to temps + if (inlineInfo->argCnt) + { + JITDUMP("\nArguments setup:\n"); for (unsigned argNum = 0; argNum < inlineInfo->argCnt; argNum++) { - const InlArgInfo& argInfo = inlArgInfo[argNum]; - const bool argIsSingleDef = !argInfo.argHasLdargaOp && !argInfo.argHasStargOp; - CallArg* arg = argInfo.arg; - GenTree* argNode = arg->GetNode(); - - assert(!argNode->OperIs(GT_RET_EXPR)); - - if (argInfo.argHasTmp) - { - noway_assert(argInfo.argIsUsed); - - /* argBashTmpNode is non-NULL iff the argument's value was - referenced exactly once by the original IL. This offers an - opportunity to avoid an intermediate temp and just insert - the original argument tree. - - However, if the temp node has been cloned somewhere while - importing (e.g. when handling isinst or dup), or if the IL - took the address of the argument, then argBashTmpNode will - be set (because the value was only explicitly retrieved - once) but the optimization cannot be applied. - */ - - GenTree* argSingleUseNode = argInfo.argBashTmpNode; - - if ((argSingleUseNode != nullptr) && !(argSingleUseNode->gtFlags & GTF_VAR_MOREUSES) && argIsSingleDef) - { - // Change the temp in-place to the actual argument. - // We currently do not support this for struct arguments, so it must not be a GT_BLK. - assert(argNode->gtOper != GT_BLK); - argSingleUseNode->ReplaceWith(argNode, this); - continue; - } - else - { - // We're going to assign the argument value to the temp we use for it in the inline body. - GenTree* store = gtNewTempStore(argInfo.argTmpNum, argNode); - - newStmt = gtNewStmt(store, callDI); - fgInsertStmtAfter(block, afterStmt, newStmt); - afterStmt = newStmt; - - DISPSTMT(afterStmt); - } - } - else if (argInfo.argIsByRefToStructLocal) - { - // Do nothing. Arg was directly substituted as we read - // the inlinee. - } - else - { - // The argument is either not used or a const or lcl var - noway_assert(!argInfo.argIsUsed || argInfo.argIsInvariant || argInfo.argIsLclVar); - noway_assert((argInfo.argIsLclVar == 0) == - (argNode->gtOper != GT_LCL_VAR || (argNode->gtFlags & GTF_GLOB_REF))); - - // If the argument has side effects, append it - if (argInfo.argHasSideEff) - { - noway_assert(argInfo.argIsUsed == false); - newStmt = nullptr; - bool append = true; - - if (argNode->gtOper == GT_BLK || argNode->gtOper == GT_MKREFANY) - { - // Don't put GT_BLK node under a GT_COMMA. - // Codegen can't deal with it. - // Just hang the address here in case there are side-effect. - newStmt = gtNewStmt(gtUnusedValNode(argNode->AsOp()->gtOp1), callDI); - } - else - { - // In some special cases, unused args with side effects can - // trigger further changes. - // - // (1) If the arg is a static field access and the field access - // was produced by a call to EqualityComparer.get_Default, the - // helper call to ensure the field has a value can be suppressed. - // This helper call is marked as a "Special DCE" helper during - // importation, over in fgGetStaticsCCtorHelper. - // - // (2) NYI. If we find that the actual arg expression - // has no side effects, we can skip appending all - // together. This will help jit TP a bit. - // - assert(!argNode->OperIs(GT_RET_EXPR)); - - // For case (1) - // - // Look for the following tree shapes - // prejit: (IND (ADD (CONST, CALL(special dce helper...)))) - // jit : (COMMA (CALL(special dce helper...), (FIELD ...))) - if (argNode->gtOper == GT_COMMA) - { - // Look for (COMMA (CALL(special dce helper...), (FIELD ...))) - GenTree* op1 = argNode->AsOp()->gtOp1; - GenTree* op2 = argNode->AsOp()->gtOp2; - if (op1->IsCall() && - ((op1->AsCall()->gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) && - op2->OperIs(GT_IND) && op2->gtGetOp1()->IsIconHandle() && - ((op2->gtFlags & GTF_EXCEPT) == 0)) - { - JITDUMP("\nPerforming special dce on unused arg [%06u]:" - " actual arg [%06u] helper call [%06u]\n", - argNode->gtTreeID, argNode->gtTreeID, op1->gtTreeID); - // Drop the whole tree - append = false; - } - } - else if (argNode->gtOper == GT_IND) - { - // Look for (IND (ADD (CONST, CALL(special dce helper...)))) - GenTree* addr = argNode->AsOp()->gtOp1; - - if (addr->gtOper == GT_ADD) - { - GenTree* op1 = addr->AsOp()->gtOp1; - GenTree* op2 = addr->AsOp()->gtOp2; - if (op1->IsCall() && - ((op1->AsCall()->gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) && - op2->IsCnsIntOrI()) - { - // Drop the whole tree - JITDUMP("\nPerforming special dce on unused arg [%06u]:" - " actual arg [%06u] helper call [%06u]\n", - argNode->gtTreeID, argNode->gtTreeID, op1->gtTreeID); - append = false; - } - } - } - } - - if (!append) - { - assert(newStmt == nullptr); - JITDUMP("Arg tree side effects were discardable, not appending anything for arg\n"); - } - else - { - // If we don't have something custom to append, - // just append the arg node as an unused value. - if (newStmt == nullptr) - { - newStmt = gtNewStmt(gtUnusedValNode(argNode), callDI); - } - - fgInsertStmtAfter(block, afterStmt, newStmt); - afterStmt = newStmt; -#ifdef DEBUG - if (verbose) - { - gtDispStmt(afterStmt); - } -#endif // DEBUG - } - } - else if (argNode->IsBoxedValue()) - { - // Try to clean up any unnecessary boxing side effects - // since the box itself will be ignored. - gtTryRemoveBoxUpstreamEffects(argNode); - } - } + fgInsertInlineeArgument(inlArgInfo[argNum], block, &afterStmt, &newStmt, callDI); } } diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 6c6edd7485694a..8e7b93dc564a63 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -1038,7 +1038,7 @@ GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall* call, GenTree* targetObjPointers = call->gtArgs.GetArgByIndex(1)->GetNode(); CORINFO_LOOKUP pLookup; info.compCompHnd->getReadyToRunDelegateCtorHelper(&ldftnToken->m_token, ldftnToken->m_tokenConstraint, - clsHnd, &pLookup); + clsHnd, info.compMethodHnd, &pLookup); if (!pLookup.lookupKind.needsRuntimeLookup) { call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, thisPointer, @@ -1050,7 +1050,8 @@ GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall* call, assert(oper != GT_FTN_ADDR); CORINFO_CONST_LOOKUP genericLookup; info.compCompHnd->getReadyToRunHelper(&ldftnToken->m_token, &pLookup.lookupKind, - CORINFO_HELP_READYTORUN_GENERIC_HANDLE, &genericLookup); + CORINFO_HELP_READYTORUN_GENERIC_HANDLE, info.compMethodHnd, + &genericLookup); GenTree* ctxTree = getRuntimeContextTree(pLookup.lookupKind.runtimeLookupKind); call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, thisPointer, targetObjPointers, ctxTree); @@ -1073,7 +1074,7 @@ GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall* call, CORINFO_LOOKUP entryPoint; info.compCompHnd->getReadyToRunDelegateCtorHelper(&ldftnToken->m_token, ldftnToken->m_tokenConstraint, - clsHnd, &entryPoint); + clsHnd, info.compMethodHnd, &entryPoint); assert(!entryPoint.lookupKind.needsRuntimeLookup); call->setEntryPoint(entryPoint.constLookup); } diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 458117f8ebfb69..ac90918815856d 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -9092,7 +9092,9 @@ GenTree* Compiler::gtNewBitCastNode(var_types type, GenTree* arg) // can't be represented in jitted code. If this happens, this method will return // nullptr. // -GenTreeAllocObj* Compiler::gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool useParent) +GenTreeAllocObj* Compiler::gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + bool useParent) { const bool mustRestoreHandle = true; bool* const pRuntimeLookup = nullptr; @@ -9108,7 +9110,7 @@ GenTreeAllocObj* Compiler::gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedTo helper = CORINFO_HELP_READYTORUN_NEW; CORINFO_LOOKUP_KIND* const pGenericLookupKind = nullptr; usingReadyToRunHelper = - info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, &lookup); + info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, callerHandle, &lookup); } #endif diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 49bdd4e5e77576..605c318ec98b86 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -1273,7 +1273,7 @@ GenTree* Compiler::impTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, assert(!fgGlobalMorph); CORINFO_GENERICHANDLE_RESULT embedInfo; - info.compCompHnd->embedGenericHandle(pResolvedToken, importParent, &embedInfo); + info.compCompHnd->embedGenericHandle(pResolvedToken, importParent, info.compMethodHnd, &embedInfo); if (pRuntimeLookup) { @@ -1485,7 +1485,7 @@ GenTreeCall* Compiler::impReadyToRunHelperToTree(CORINFO_RESOLVED_TOKEN* pResolv GenTree* arg1) { CORINFO_CONST_LOOKUP lookup; - if (!info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, &lookup)) + if (!info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, info.compMethodHnd, &lookup)) { return nullptr; } @@ -1548,30 +1548,56 @@ GenTree* Compiler::impMethodPointer(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORI GenTree* Compiler::getRuntimeContextTree(CORINFO_RUNTIME_LOOKUP_KIND kind) { - GenTree* ctxTree = nullptr; + GenTree* ctxTree; // Collectible types requires that for shared generic code, if we use the generic context parameter - // that we report it. (This is a conservative approach, we could detect some cases particularly when the - // context parameter is this that we don't need the eager reporting logic.) - lvaGenericsContextInUse = true; + // that we report it. Conservatively mark the root method as using generic context, MARK_LOCAL_VARS phase + // will clean it up if it turns out to be unnecessary. + impInlineRoot()->lvaGenericsContextInUse = true; - Compiler* pRoot = impInlineRoot(); - - if (kind == CORINFO_LOOKUP_THISOBJ) + // Always use generic context from the callsite if we're inlining and it's available. + if (compIsForInlining() && (impInlineInfo->inlInstParamArgInfo != nullptr)) { - // this Object - ctxTree = gtNewLclvNode(pRoot->info.compThisArg, TYP_REF); - ctxTree->gtFlags |= GTF_VAR_CONTEXT; + // Create a dummy lclInfo node, we know that nobody's going to do stloc or take address + // of the generic context, so we don't need to scan IL for it. + InlLclVarInfo lclInfo = {}; + lclInfo.lclTypeInfo = TYP_I_IMPL; + ctxTree = impInlineFetchArg(*impInlineInfo->inlInstParamArgInfo, lclInfo); + assert(ctxTree != nullptr); + assert(ctxTree->TypeIs(TYP_I_IMPL)); + // We don't need to worry about GTF_VAR_CONTEXT here, it should be set on the callsite anyway. + } + else if (kind == CORINFO_LOOKUP_THISOBJ) + { + // Use "this" from the callsite if we're inlining + if (compIsForInlining()) + { + // "this" is always the first argument in inlArgInfo + assert(impInlineInfo->argCnt > 0); + assert(impInlineInfo->inlArgInfo[0].argIsThis); + + ctxTree = impInlineFetchArg(impInlineInfo->inlArgInfo[0], impInlineInfo->lclVarInfo[0]); + + // "this" is expected to be always a local, and we must mark it as a context + assert(ctxTree->OperIs(GT_LCL_VAR)); + ctxTree->gtFlags |= GTF_VAR_CONTEXT; + } + else + { + assert(info.compThisArg != BAD_VAR_NUM); + ctxTree = gtNewLclvNode(info.compThisArg, TYP_REF); + ctxTree->gtFlags |= GTF_VAR_CONTEXT; + } // context is the method table pointer of the this object ctxTree = gtNewMethodTableLookup(ctxTree); } else { - assert(kind == CORINFO_LOOKUP_METHODPARAM || kind == CORINFO_LOOKUP_CLASSPARAM); + assert((kind == CORINFO_LOOKUP_METHODPARAM) || (kind == CORINFO_LOOKUP_CLASSPARAM)); // Exact method descriptor as passed in - ctxTree = gtNewLclvNode(pRoot->info.compTypeCtxtArg, TYP_I_IMPL); + ctxTree = gtNewLclvNode(impInlineRoot()->info.compTypeCtxtArg, TYP_I_IMPL); ctxTree->gtFlags |= GTF_VAR_CONTEXT; } return ctxTree; @@ -1643,6 +1669,9 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken GenTree* slotPtrTree = ctxTree; GenTree* indOffTree = nullptr; + // TODO-CQ: consider relaxing where it's safe to do so + const bool ctxTreeIsInvariant = !compIsForInlining(); + // Applied repeated indirections for (WORD i = 0; i < pRuntimeLookup->indirections; i++) { @@ -1654,7 +1683,8 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken if (i != 0) { - slotPtrTree = gtNewIndir(TYP_I_IMPL, slotPtrTree, GTF_IND_NONFAULTING | GTF_IND_INVARIANT); + slotPtrTree = gtNewIndir(TYP_I_IMPL, slotPtrTree, + ctxTreeIsInvariant ? (GTF_IND_NONFAULTING | GTF_IND_INVARIANT) : GTF_EMPTY); } if ((i == 1 && pRuntimeLookup->indirectFirstOffset) || (i == 2 && pRuntimeLookup->indirectSecondOffset)) @@ -1677,7 +1707,8 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken return slotPtrTree; } - slotPtrTree = gtNewIndir(TYP_I_IMPL, slotPtrTree, GTF_IND_NONFAULTING | GTF_IND_INVARIANT); + slotPtrTree = + gtNewIndir(TYP_I_IMPL, slotPtrTree, ctxTreeIsInvariant ? (GTF_IND_NONFAULTING | GTF_IND_INVARIANT) : GTF_EMPTY); return slotPtrTree; } @@ -3236,7 +3267,7 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken) Statement* const cursor = impLastStmt; const bool useParent = false; - op1 = gtNewAllocObjNode(pResolvedToken, useParent); + op1 = gtNewAllocObjNode(pResolvedToken, info.compMethodHnd, useParent); if (op1 == nullptr) { // If we fail to create the newobj node, we must be inlining @@ -6286,7 +6317,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (compIsForInlining()) { - op1 = impInlineFetchArg(lclNum, impInlineInfo->inlArgInfo, impInlineInfo->lclVarInfo); + op1 = impInlineFetchArg(impInlineInfo->inlArgInfo[lclNum], impInlineInfo->lclVarInfo[lclNum]); noway_assert(op1->gtOper == GT_LCL_VAR); lclNum = op1->AsLclVar()->GetLclNum(); @@ -6491,7 +6522,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) // In IL, LDARGA(_S) is used to load the byref managed pointer of struct argument, // followed by a ldfld to load the field. - op1 = impInlineFetchArg(lclNum, impInlineInfo->inlArgInfo, impInlineInfo->lclVarInfo); + op1 = impInlineFetchArg(impInlineInfo->inlArgInfo[lclNum], impInlineInfo->lclVarInfo[lclNum]); if (op1->gtOper != GT_LCL_VAR) { compInlineResult->NoteFatal(InlineObservation::CALLSITE_LDARGA_NOT_LOCAL_VAR); @@ -8487,7 +8518,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) } const bool useParent = true; - op1 = gtNewAllocObjNode(&resolvedToken, useParent); + op1 = gtNewAllocObjNode(&resolvedToken, info.compMethodHnd, useParent); if (op1 == nullptr) { return; @@ -10465,7 +10496,8 @@ void Compiler::impLoadArg(unsigned ilArgNum, IL_OFFSET offset) tiRetVal = typeInfo(type); } - impPushOnStack(impInlineFetchArg(ilArgNum, impInlineInfo->inlArgInfo, impInlineInfo->lclVarInfo), tiRetVal); + impPushOnStack(impInlineFetchArg(impInlineInfo->inlArgInfo[ilArgNum], impInlineInfo->lclVarInfo[ilArgNum]), + tiRetVal); } else { @@ -12788,9 +12820,27 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo) inlArgInfo[ilArgCnt].argIsThis = true; break; case WellKnownArg::RetBuffer: + // This does not appear in the table of inline arg info; do not include them + continue; case WellKnownArg::InstParam: - // These do not appear in the table of inline arg info; do not include them + { + InlArgInfo* ctxInfo = new (this, CMK_Inlining) InlArgInfo{}; + ctxInfo->arg = &arg; + ctxInfo->argTmpNum = BAD_VAR_NUM; + ctxInfo->argIsLclVar = arg.GetNode()->OperIs(GT_LCL_VAR); + if (arg.GetNode()->IsCnsIntOrI()) + { + ctxInfo->argIsInvariant = true; + } + else + { + // Conservative approach + ctxInfo->argHasSideEff = true; + ctxInfo->argHasGlobRef = true; + } + pInlineInfo->inlInstParamArgInfo = ctxInfo; continue; + } default: break; } @@ -13161,9 +13211,8 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas // impInlineFetchArg: return tree node for argument value in an inlinee // // Arguments: -// lclNum -- argument number in inlinee IL -// inlArgInfo -- argument info for inlinee -// lclVarInfo -- var info for inlinee +// argInfo -- argument info for inlinee +// lclInfo -- var info for inlinee // // Returns: // Tree for the argument's value. Often an inlinee-scoped temp @@ -13190,15 +13239,13 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas // This method will side effect inlArgInfo. It should only be called // for actual uses of the argument in the inlinee. -GenTree* Compiler::impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, InlLclVarInfo* lclVarInfo) +GenTree* Compiler::impInlineFetchArg(InlArgInfo& argInfo, const InlLclVarInfo& lclInfo) { // Cache the relevant arg and lcl info for this argument. // We will modify argInfo but not lclVarInfo. - InlArgInfo& argInfo = inlArgInfo[lclNum]; - const InlLclVarInfo& lclInfo = lclVarInfo[lclNum]; - const bool argCanBeModified = argInfo.argHasLdargaOp || argInfo.argHasStargOp; - const var_types lclTyp = lclInfo.lclTypeInfo; - GenTree* op1 = nullptr; + const bool argCanBeModified = argInfo.argHasLdargaOp || argInfo.argHasStargOp; + const var_types lclTyp = lclInfo.lclTypeInfo; + GenTree* op1 = nullptr; GenTree* argNode = argInfo.arg->GetNode(); assert(!argNode->OperIs(GT_RET_EXPR)); @@ -13249,7 +13296,6 @@ GenTree* Compiler::impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, In if (argInfo.argIsUsed || ((lclTyp == TYP_BYREF) && (op1->TypeGet() != TYP_BYREF))) { assert(op1->gtOper == GT_LCL_VAR); - assert(lclNum == op1->AsLclVar()->gtLclILoffs); // Create a new lcl var node - remember the argument lclNum op1 = impCreateLocalNode(argLclNum DEBUGARG(op1->AsLclVar()->gtLclILoffs)); @@ -13362,7 +13408,7 @@ GenTree* Compiler::impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, In !argInfo.argHasCallerLocalRef)) { /* Get a *LARGE* LCL_VAR node */ - op1 = gtNewLclLNode(tmpNum, genActualType(lclTyp) DEBUGARG(lclNum)); + op1 = gtNewLclLNode(tmpNum, genActualType(lclTyp)); /* Record op1 as the very first use of this argument. If there are no further uses of the arg, we may be diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 7796f2f9700f1e..68eadeaabe4c13 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3367,7 +3367,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, resolvedToken.tokenType = CORINFO_TOKENKIND_Method; CORINFO_GENERICHANDLE_RESULT embedInfo; - info.compCompHnd->expandRawHandleIntrinsic(&resolvedToken, &embedInfo); + info.compCompHnd->expandRawHandleIntrinsic(&resolvedToken, info.compMethodHnd, &embedInfo); GenTree* rawHandle = impLookupToTree(&resolvedToken, &embedInfo.lookup, gtTokenToIconFlags(memberRef), embedInfo.compileTimeHandle); diff --git a/src/coreclr/jit/inline.h b/src/coreclr/jit/inline.h index dca92e39241e49..342dc3fca5d238 100644 --- a/src/coreclr/jit/inline.h +++ b/src/coreclr/jit/inline.h @@ -686,6 +686,7 @@ struct InlineInfo unsigned argCnt; InlArgInfo inlArgInfo[MAX_INL_ARGS + 1]; + InlArgInfo* inlInstParamArgInfo; int lclTmpNum[MAX_INL_LCLS]; // map local# -> temp# (-1 if unused) InlLclVarInfo lclVarInfo[MAX_INL_LCLS + MAX_INL_ARGS + 1]; // type information from local sig diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index ff9b449d388fc1..f4b651559ee0fd 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2337,7 +2337,9 @@ bool Compiler::fgCreateFiltersForGenericExceptions() info.compCompHnd->resolveToken(&resolvedToken); CORINFO_GENERICHANDLE_RESULT embedInfo; - info.compCompHnd->embedGenericHandle(&resolvedToken, true, &embedInfo); + // NOTE: inlining is done at this point, so we don't know which method contained this token. + // It's fine because currently this is never used for something that belongs to an inlinee. + info.compCompHnd->embedGenericHandle(&resolvedToken, true, info.compMethodHnd, &embedInfo); if (!embedInfo.lookup.lookupKind.needsRuntimeLookup) { // Exception type does not need runtime lookup diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 55787580cc1df7..f2e47ae2ddac44 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1540,7 +1540,7 @@ unsigned Compiler::compMapILvarNum(unsigned ILvarNum) else if (ILvarNum == (unsigned)ICorDebugInfo::TYPECTXT_ILNUM) { noway_assert(info.compTypeCtxtArg >= 0); - varNum = unsigned(info.compTypeCtxtArg); + varNum = info.compTypeCtxtArg; } else if (ILvarNum < info.compILargsCount) { @@ -1593,7 +1593,7 @@ unsigned Compiler::compMap2ILvarNum(unsigned varNum) const // We create an extra argument for the type context parameter // needed for shared generic code. - if ((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) && varNum == (unsigned)info.compTypeCtxtArg) + if ((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) && varNum == info.compTypeCtxtArg) { return (unsigned)ICorDebugInfo::TYPECTXT_ILNUM; } @@ -1606,7 +1606,7 @@ unsigned Compiler::compMap2ILvarNum(unsigned varNum) const #endif // FEATURE_FIXED_OUT_ARGS // Now mutate varNum to remove extra parameters from the count. - if ((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) && varNum > (unsigned)info.compTypeCtxtArg) + if ((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) && varNum > info.compTypeCtxtArg) { varNum--; } @@ -4357,7 +4357,7 @@ PhaseStatus Compiler::lvaMarkLocalVars() else if (lvaReportParamTypeArg()) { // We should have a context arg. - assert(info.compTypeCtxtArg != (int)BAD_VAR_NUM); + assert(info.compTypeCtxtArg != BAD_VAR_NUM); lvaGetDesc(info.compTypeCtxtArg)->lvImplicitlyReferenced = reportParamTypeArg; } @@ -5498,7 +5498,7 @@ void Compiler::lvaAssignVirtualFrameOffsetsToArgs() //@GENERICS: extra argument for instantiation info if (info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) { - noway_assert(lclNum == (unsigned)info.compTypeCtxtArg); + noway_assert(lclNum == info.compTypeCtxtArg); argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum++, REGSIZE_BYTES, argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); } @@ -5607,7 +5607,7 @@ void Compiler::lvaAssignVirtualFrameOffsetsToArgs() //@GENERICS: extra argument for instantiation info if (info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) { - noway_assert(lclNum == (unsigned)info.compTypeCtxtArg); + noway_assert(lclNum == info.compTypeCtxtArg); argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum++, REGSIZE_BYTES, argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 30b83dcc6f9003..90d599e4984068 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -7006,7 +7006,8 @@ GenTree* Compiler::getVirtMethodPointerTree(GenTree* thisPtr, } //------------------------------------------------------------------------ -// getTokenHandleTree: get a handle tree for a token +// getTokenHandleTree: get a handle tree for a token. This method should never +// be called for tokens imported from inlinees. // // Arguments: // pResolvedToken - token to get a handle for @@ -7018,7 +7019,14 @@ GenTree* Compiler::getVirtMethodPointerTree(GenTree* thisPtr, GenTree* Compiler::getTokenHandleTree(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool parent) { CORINFO_GENERICHANDLE_RESULT embedInfo; - info.compCompHnd->embedGenericHandle(pResolvedToken, parent, &embedInfo); + + // NOTE: inlining is done at this point, so we don't know which method contained this token. + // It's fine because currently this is never used for something that belongs to an inlinee. + // Namely, we currently use it for: + // 1) Methods with EH are never inlined + // 2) Methods with explicit tail calls are never inlined + // + info.compCompHnd->embedGenericHandle(pResolvedToken, parent, info.compMethodHnd, &embedInfo); GenTree* result = getLookupTree(pResolvedToken, &embedInfo.lookup, gtTokenToIconFlags(pResolvedToken->token), embedInfo.compileTimeHandle); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 10c0b1949182b1..09ea54f989fde5 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -291,12 +291,12 @@ private static byte _resolveVirtualMethod(IntPtr thisHandle, IntPtr* ppException } [UnmanagedCallersOnly] - private static void _expandRawHandleIntrinsic(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult) + private static void _expandRawHandleIntrinsic(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { var _this = GetThis(thisHandle); try { - _this.expandRawHandleIntrinsic(ref *pResolvedToken, ref *pResult); + _this.expandRawHandleIntrinsic(ref *pResolvedToken, callerHandle, ref *pResult); } catch (Exception ex) { @@ -1033,12 +1033,12 @@ private static byte _getStringChar(IntPtr thisHandle, IntPtr* ppException, CORIN } [UnmanagedCallersOnly] - private static byte _getReadyToRunHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup) + private static byte _getReadyToRunHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_CONST_LOOKUP* pLookup) { var _this = GetThis(thisHandle); try { - return _this.getReadyToRunHelper(ref *pResolvedToken, ref *pGenericLookupKind, id, ref *pLookup) ? (byte)1 : (byte)0; + return _this.getReadyToRunHelper(ref *pResolvedToken, ref *pGenericLookupKind, id, callerHandle, ref *pLookup) ? (byte)1 : (byte)0; } catch (Exception ex) { @@ -1048,12 +1048,12 @@ private static byte _getReadyToRunHelper(IntPtr thisHandle, IntPtr* ppException, } [UnmanagedCallersOnly] - private static void _getReadyToRunDelegateCtorHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_STRUCT_* delegateType, CORINFO_LOOKUP* pLookup) + private static void _getReadyToRunDelegateCtorHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_STRUCT_* delegateType, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_LOOKUP* pLookup) { var _this = GetThis(thisHandle); try { - _this.getReadyToRunDelegateCtorHelper(ref *pTargetMethod, targetConstraint, delegateType, ref *pLookup); + _this.getReadyToRunDelegateCtorHelper(ref *pTargetMethod, targetConstraint, delegateType, callerHandle, ref *pLookup); } catch (Exception ex) { @@ -2007,12 +2007,12 @@ private static CorInfoHelpFunc _getLazyStringLiteralHelper(IntPtr thisHandle, In } [UnmanagedCallersOnly] - private static void _embedGenericHandle(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, byte fEmbedParent, CORINFO_GENERICHANDLE_RESULT* pResult) + private static void _embedGenericHandle(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, byte fEmbedParent, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { var _this = GetThis(thisHandle); try { - _this.embedGenericHandle(ref *pResolvedToken, fEmbedParent != 0, ref *pResult); + _this.embedGenericHandle(ref *pResolvedToken, fEmbedParent != 0, callerHandle, ref *pResult); } catch (Exception ex) { @@ -2600,7 +2600,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[16] = (delegate* unmanaged)&_getUnboxedEntry; callbacks[17] = (delegate* unmanaged)&_getDefaultComparerClass; callbacks[18] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; - callbacks[19] = (delegate* unmanaged)&_expandRawHandleIntrinsic; + callbacks[19] = (delegate* unmanaged)&_expandRawHandleIntrinsic; callbacks[20] = (delegate* unmanaged)&_isIntrinsicType; callbacks[21] = (delegate* unmanaged)&_getUnmanagedCallConv; callbacks[22] = (delegate* unmanaged)&_pInvokeMarshalingRequired; @@ -2650,8 +2650,8 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[66] = (delegate* unmanaged)&_isObjectImmutable; callbacks[67] = (delegate* unmanaged)&_getStringChar; callbacks[68] = (delegate* unmanaged)&_getObjectType; - callbacks[69] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[70] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[69] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[70] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; callbacks[71] = (delegate* unmanaged)&_initClass; callbacks[72] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; callbacks[73] = (delegate* unmanaged)&_getBuiltinClass; @@ -2716,7 +2716,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[132] = (delegate* unmanaged)&_embedClassHandle; callbacks[133] = (delegate* unmanaged)&_embedMethodHandle; callbacks[134] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[135] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[135] = (delegate* unmanaged)&_embedGenericHandle; callbacks[136] = (delegate* unmanaged)&_getLocationOfThisType; callbacks[137] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; callbacks[138] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index c68736fde01061..8d6ecabaa77c57 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -182,7 +182,7 @@ FUNCTIONS CORINFO_METHOD_HANDLE getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); CORINFO_CLASS_HANDLE getDefaultComparerClass(CORINFO_CLASS_HANDLE elemType); CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE elemType); - void expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_GENERICHANDLE_RESULT * pResult); + void expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT * pResult); bool isIntrinsicType( CORINFO_CLASS_HANDLE classHnd ); CorInfoCallConvExtension getUnmanagedCallConv( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig, bool* pSuppressGCTransition); bool pInvokeMarshalingRequired( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig ); @@ -232,8 +232,8 @@ FUNCTIONS bool isObjectImmutable(CORINFO_OBJECT_HANDLE objPtr) bool getStringChar(CORINFO_OBJECT_HANDLE strObj, int index, uint16_t* value); CORINFO_CLASS_HANDLE getObjectType(CORINFO_OBJECT_HANDLE objPtr) - bool getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP *pLookup) - void getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP *pLookup) + bool getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP *pLookup) + void getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP *pLookup) 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) @@ -298,7 +298,7 @@ FUNCTIONS CORINFO_CLASS_HANDLE embedClassHandle(CORINFO_CLASS_HANDLE handle, void **ppIndirection); CORINFO_METHOD_HANDLE embedMethodHandle(CORINFO_METHOD_HANDLE handle, void **ppIndirection); CORINFO_FIELD_HANDLE embedFieldHandle(CORINFO_FIELD_HANDLE handle, void **ppIndirection); - void embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fEmbedParent, CORINFO_GENERICHANDLE_RESULT * pResult); + void embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fEmbedParent, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT * pResult); void getLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* pLookupKind); void getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup); void* GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void ** ppIndirection); 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 96911a9289804d..aba1e6bbd36080 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -827,7 +827,7 @@ public void CompileMethod(MethodWithGCInfo methodCodeNodeNeedingCode, Logger log } } - private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) + private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_CONST_LOOKUP pLookup) { switch (id) { @@ -913,7 +913,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref helperArg = new FieldWithToken(fieldDesc, HandleToModuleToken(ref pResolvedToken)); } - GenericContext methodContext = new GenericContext(entityFromContext(pResolvedToken.tokenContext)); + var methodContext = new GenericContext(HandleToObject(callerHandle)); ISymbolNode helper = _compilation.SymbolNodeFactory.GenericLookupHelper( pGenericLookupKind.runtimeLookupKind, helperId, @@ -928,7 +928,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref return true; } - private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_LOOKUP pLookup) + private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_STRUCT_* delegateType, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_LOOKUP pLookup) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything @@ -958,6 +958,7 @@ private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetM unboxing: false, context: typeOrMethodContext); + // runtime lookup is not needed, callerHandle is unused pLookup.lookupKind.needsRuntimeLookup = false; pLookup.constLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.DelegateCtor(delegateTypeDesc, targetMethod)); } @@ -2185,7 +2186,7 @@ private void ceeInfoGetCallInfo( useInstantiatingStub = true; } - ComputeRuntimeLookupForSharedGenericToken(entryKind, ref pResolvedToken, pConstrainedResolvedToken, originalMethod, ref pResult->codePointerOrStubLookup); + ComputeRuntimeLookupForSharedGenericToken(entryKind, ref pResolvedToken, pConstrainedResolvedToken, originalMethod, HandleToObject(callerHandle), ref pResult->codePointerOrStubLookup); } } else @@ -2275,7 +2276,7 @@ private void ceeInfoGetCallInfo( if (pResult->exactContextNeedsRuntimeLookup) { - ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind.DispatchStubAddrSlot, ref pResolvedToken, null, originalMethod, ref pResult->codePointerOrStubLookup); + ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind.DispatchStubAddrSlot, ref pResolvedToken, null, originalMethod, HandleToObject(callerHandle), ref pResult->codePointerOrStubLookup); } else { @@ -2558,8 +2559,11 @@ private void ComputeRuntimeLookupForSharedGenericToken( ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, MethodDesc templateMethod, + MethodDesc callerHandle, ref CORINFO_LOOKUP pResultLookup) { + Debug.Assert(callerHandle != null); + pResultLookup.lookupKind.needsRuntimeLookup = true; pResultLookup.lookupKind.runtimeLookupFlags = 0; @@ -2573,15 +2577,7 @@ private void ComputeRuntimeLookupForSharedGenericToken( pResult.indirections = CORINFO.USEHELPER; pResult.sizeOffset = CORINFO.CORINFO_NO_SIZE_CHECK; - // Runtime lookups in inlined contexts are not supported by the runtime for now - if (pResolvedToken.tokenContext != contextFromMethodBeingCompiled()) - { - pResultLookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_NOT_SUPPORTED; - return; - } - - MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); - TypeDesc contextType = typeFromContext(pResolvedToken.tokenContext); + MethodDesc contextMethod = callerHandle; // There is a pathological case where invalid IL refereces __Canon type directly, but there is no dictionary availabled to store the lookup. if (!contextMethod.IsSharedByGenericInstantiations) @@ -2643,7 +2639,7 @@ private void ComputeRuntimeLookupForSharedGenericToken( // different way that is more version resilient... plus we can't have pointers to existing MTs/MDs in the sigs) } - private void ceeInfoEmbedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult) + private void ceeInfoEmbedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fEmbedParent, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_GENERICHANDLE_RESULT pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything @@ -2727,7 +2723,7 @@ private void ceeInfoEmbedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken throw new NotImplementedException(pResult.handleType.ToString()); } - ComputeRuntimeLookupForSharedGenericToken(entryKind, ref pResolvedToken, pConstrainedResolvedToken: null, templateMethod, ref pResult.lookup); + ComputeRuntimeLookupForSharedGenericToken(entryKind, ref pResolvedToken, pConstrainedResolvedToken: null, templateMethod, HandleToObject(callerHandle), ref pResult.lookup); } else { @@ -2752,9 +2748,9 @@ private void ceeInfoEmbedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken return null; } - private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult) + private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fEmbedParent, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_GENERICHANDLE_RESULT pResult) { - ceeInfoEmbedGenericHandle(ref pResolvedToken, fEmbedParent, ref pResult); + ceeInfoEmbedGenericHandle(ref pResolvedToken, fEmbedParent, callerHandle, ref pResult); Debug.Assert(pResult.compileTimeHandle != null); @@ -2957,7 +2953,7 @@ private void getGSCookie(IntPtr* pCookieVal, IntPtr** ppCookieVal) private void getMethodVTableOffset(CORINFO_METHOD_STRUCT_* method, ref uint offsetOfIndirection, ref uint offsetAfterIndirection, ref bool isRelative) { throw new NotImplementedException("getMethodVTableOffset"); } - private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult) + private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_GENERICHANDLE_RESULT pResult) { throw new NotImplementedException("expandRawHandleIntrinsic"); } private void* getMethodSync(CORINFO_METHOD_STRUCT_* ftn, ref void* ppIndirection) 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 b482a153539af0..1e72961928078d 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -239,27 +239,30 @@ private static CORINFO_RUNTIME_LOOKUP_KIND GetLookupKindFromContextSource(Generi } } - private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object entity, ReadyToRunHelperId helperId, ref CORINFO_LOOKUP lookup) + private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object entity, ReadyToRunHelperId helperId, MethodDesc callerHandle, ref CORINFO_LOOKUP lookup) { + Debug.Assert(callerHandle != null); + if (_compilation.NeedsRuntimeLookup(helperId, entity)) { lookup.lookupKind.needsRuntimeLookup = true; lookup.runtimeLookup.signature = null; - // Do not bother computing the runtime lookup if we are inlining. The JIT is going - // to abort the inlining attempt anyway. - if (pResolvedToken.tokenContext != contextFromMethodBeingCompiled()) - { - lookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_NOT_SUPPORTED; - return; - } - - MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); - - GenericDictionaryLookup genericLookup = _compilation.ComputeGenericLookup(contextMethod, helperId, entity); + GenericDictionaryLookup genericLookup = _compilation.ComputeGenericLookup(callerHandle, helperId, entity); if (genericLookup.UseHelper) { + // If this is from a different context and we need a ReadyToRun helper, abort. + // The ReadyToRun helpers need to be able to declare the dependencies and we can't + // currently do it for an inline. This is not a big issue because ReadyToRun helpers + // in optimized code only happen in special build configurations (such as + // `-O --noscan` or multimodule build). + if (pResolvedToken.tokenContext != contextFromMethodBeingCompiled()) + { + lookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_NOT_SUPPORTED; + return; + } + lookup.runtimeLookup.indirections = CORINFO.USEHELPER; lookup.lookupKind.runtimeLookupFlags = (ushort)genericLookup.HelperId; lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(genericLookup.HelperObject); @@ -303,7 +306,7 @@ private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object ent } } - private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) + private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_CONST_LOOKUP pLookup) { switch (id) { @@ -330,11 +333,11 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref Debug.Assert(pResolvedToken.token == 0 && pResolvedToken.tokenScope == null); Debug.Assert(pGenericLookupKind.needsRuntimeLookup); - DefType typeToInitialize = (DefType)MethodBeingCompiled.OwningType; + DefType typeToInitialize = (DefType)HandleToObject(callerHandle).OwningType; Debug.Assert(typeToInitialize.IsCanonicalSubtype(CanonicalFormKind.Any)); DefType helperArg = typeToInitialize.ConvertToSharedRuntimeDeterminedForm(); - ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, ReadyToRunHelperId.GetNonGCStaticBase, helperArg); + ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, ReadyToRunHelperId.GetNonGCStaticBase, HandleToObject(callerHandle), helperArg); pLookup = CreateConstLookupToSymbol(helper); } break; @@ -344,7 +347,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref ReadyToRunHelperId helperId = (ReadyToRunHelperId)pGenericLookupKind.runtimeLookupFlags; object helperArg = HandleToObject(pGenericLookupKind.runtimeLookupArgs); - ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, helperId, helperArg); + ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, helperId, HandleToObject(callerHandle), helperArg); pLookup = CreateConstLookupToSymbol(helper); } break; @@ -354,7 +357,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref return true; } - private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_LOOKUP pLookup) + private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_STRUCT_* delegateType, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_LOOKUP pLookup) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything @@ -433,11 +436,7 @@ private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetM { pLookup.lookupKind.needsRuntimeLookup = true; - MethodDesc contextMethod = methodFromContext(pTargetMethod.tokenContext); - - // We should not be inlining these. RyuJIT should have aborted inlining already. - Debug.Assert(contextMethod == MethodBeingCompiled); - + MethodDesc contextMethod = HandleToObject(callerHandle); pLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); pLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.DelegateCtor; pLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(delegateInfo); @@ -1053,16 +1052,16 @@ private void SetDebugInformation(IMethodNode methodCodeNodeNeedingCode, MethodIL _debugInfo = _compilation.GetDebugInfo(methodIL); } - private ISymbolNode GetGenericLookupHelper(CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind, ReadyToRunHelperId helperId, object helperArgument) + private ISymbolNode GetGenericLookupHelper(CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind, ReadyToRunHelperId helperId, MethodDesc callerHandle, object helperArgument) { if (runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ || runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM) { - return _compilation.NodeFactory.ReadyToRunHelperFromTypeLookup(helperId, helperArgument, MethodBeingCompiled.OwningType); + return _compilation.NodeFactory.ReadyToRunHelperFromTypeLookup(helperId, helperArgument, callerHandle.OwningType); } Debug.Assert(runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM); - return _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup(helperId, helperArgument, MethodBeingCompiled); + return _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup(helperId, helperArgument, callerHandle); } private CorInfoHelpFunc getCastingHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fThrowing) @@ -1414,6 +1413,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO ComputeLookup(ref pResolvedToken, targetOfLookup, ReadyToRunHelperId.MethodEntry, + HandleToObject(callerHandle), ref pResult->codePointerOrStubLookup); targetIsFatFunctionPointer = true; @@ -1435,20 +1435,9 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO pResult->codePointerOrStubLookup.lookupKind.needsRuntimeLookup = true; pResult->codePointerOrStubLookup.lookupKind.runtimeLookupFlags = 0; pResult->codePointerOrStubLookup.runtimeLookup.indirections = CORINFO.USEHELPER; - - // Do not bother computing the runtime lookup if we are inlining. The JIT is going - // to abort the inlining attempt anyway. - if (pResolvedToken.tokenContext == contextFromMethodBeingCompiled()) - { - MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); - pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); - pResult->codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodEntry; - pResult->codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken)); - } - else - { - pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_NOT_SUPPORTED; - } + pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(HandleToObject(callerHandle)); + pResult->codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodEntry; + pResult->codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken)); } else { @@ -1565,6 +1554,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO ComputeLookup(ref pResolvedToken, constrainedCallInfo, constrainedHelperId, + HandleToObject(callerHandle), ref pResult->codePointerOrStubLookup); targetIsFatFunctionPointer = true; @@ -1587,6 +1577,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO ComputeLookup(ref pResolvedToken, targetOfLookup, ReadyToRunHelperId.MethodHandle, + HandleToObject(callerHandle), ref pResult->codePointerOrStubLookup); // RyuJIT will assert if we report CORINFO_CALLCONV_PARAMTYPE for a result of a ldvirtftn @@ -1604,6 +1595,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO ComputeLookup(ref pResolvedToken, GetRuntimeDeterminedObjectForToken(ref pResolvedToken), ReadyToRunHelperId.VirtualDispatchCell, + HandleToObject(callerHandle), ref pResult->codePointerOrStubLookup); Debug.Assert(pResult->codePointerOrStubLookup.lookupKind.needsRuntimeLookup); } @@ -1721,7 +1713,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO } } - private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult) + private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool fEmbedParent, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_GENERICHANDLE_RESULT pResult) { #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything @@ -1812,7 +1804,7 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool Debug.Assert(pResult.compileTimeHandle != null); - ComputeLookup(ref pResolvedToken, target, helperId, ref pResult.lookup); + ComputeLookup(ref pResolvedToken, target, helperId, HandleToObject(callerHandle), ref pResult.lookup); } private CORINFO_METHOD_STRUCT_* embedMethodHandle(CORINFO_METHOD_STRUCT_* handle, ref void* ppIndirection) @@ -1857,7 +1849,7 @@ private void getMethodVTableOffset(CORINFO_METHOD_STRUCT_* method, ref uint offs offsetAfterIndirection = (uint)(EETypeNode.GetVTableOffset(pointerSize) + slot * pointerSize); } - private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult) + private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, ref CORINFO_GENERICHANDLE_RESULT pResult) { // Resolved token as a potentially RuntimeDetermined object. MethodDesc method = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken); @@ -1867,15 +1859,15 @@ private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, switch (method.Name) { case "Of": - ComputeLookup(ref pResolvedToken, method.Instantiation[0], ReadyToRunHelperId.TypeHandle, ref pResult.lookup); + ComputeLookup(ref pResolvedToken, method.Instantiation[0], ReadyToRunHelperId.TypeHandle, HandleToObject(callerHandle), ref pResult.lookup); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_CLASS; break; case "DefaultConstructorOf": - ComputeLookup(ref pResolvedToken, method.Instantiation[0], ReadyToRunHelperId.DefaultConstructor, ref pResult.lookup); + ComputeLookup(ref pResolvedToken, method.Instantiation[0], ReadyToRunHelperId.DefaultConstructor, HandleToObject(callerHandle), ref pResult.lookup); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_METHOD; break; case "AllocatorOf": - ComputeLookup(ref pResolvedToken, method.Instantiation[0], ReadyToRunHelperId.ObjectAllocator, ref pResult.lookup); + ComputeLookup(ref pResolvedToken, method.Instantiation[0], ReadyToRunHelperId.ObjectAllocator, HandleToObject(callerHandle), ref pResult.lookup); pResult.handleType = CorInfoGenericHandleType.CORINFO_HANDLETYPE_UNKNOWN; break; default: @@ -2128,46 +2120,41 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_READYTORUN_HELPER; pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE; - // Don't try to compute the runtime lookup if we're inlining. The JIT is going to abort the inlining - // attempt anyway. - if (pResolvedToken.tokenContext == contextFromMethodBeingCompiled()) - { - MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); + MethodDesc contextMethod = HandleToObject(callerHandle); - FieldDesc runtimeDeterminedField = (FieldDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken); + FieldDesc runtimeDeterminedField = (FieldDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken); - ReadyToRunHelperId helperId; + ReadyToRunHelperId helperId; - // Find out what kind of base do we need to look up. - if (field.IsThreadStatic) - { - helperId = ReadyToRunHelperId.GetThreadStaticBase; - } - else if (field.HasGCStaticBase) - { - helperId = ReadyToRunHelperId.GetGCStaticBase; - } - else - { - helperId = ReadyToRunHelperId.GetNonGCStaticBase; - } - - // What generic context do we look up the base from. - ISymbolNode helper; - if (contextMethod.AcquiresInstMethodTableFromThis() || contextMethod.RequiresInstMethodTableArg()) - { - helper = _compilation.NodeFactory.ReadyToRunHelperFromTypeLookup( - helperId, runtimeDeterminedField.OwningType, contextMethod.OwningType); - } - else - { - Debug.Assert(contextMethod.RequiresInstMethodDescArg()); - helper = _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup( - helperId, runtimeDeterminedField.OwningType, contextMethod); - } + // Find out what kind of base do we need to look up. + if (field.IsThreadStatic) + { + helperId = ReadyToRunHelperId.GetThreadStaticBase; + } + else if (field.HasGCStaticBase) + { + helperId = ReadyToRunHelperId.GetGCStaticBase; + } + else + { + helperId = ReadyToRunHelperId.GetNonGCStaticBase; + } - pResult->fieldLookup = CreateConstLookupToSymbol(helper); + // What generic context do we look up the base from. + ISymbolNode helper; + if (contextMethod.AcquiresInstMethodTableFromThis() || contextMethod.RequiresInstMethodTableArg()) + { + helper = _compilation.NodeFactory.ReadyToRunHelperFromTypeLookup( + helperId, runtimeDeterminedField.OwningType, contextMethod.OwningType); } + else + { + Debug.Assert(contextMethod.RequiresInstMethodDescArg()); + helper = _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup( + helperId, runtimeDeterminedField.OwningType, contextMethod); + } + + pResult->fieldLookup = CreateConstLookupToSymbol(helper); } else { diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 120c2166cd321e..754394f16ee9eb 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -30,7 +30,7 @@ struct JitInterfaceCallbacks CORINFO_METHOD_HANDLE (* getUnboxedEntry)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); CORINFO_CLASS_HANDLE (* getDefaultComparerClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE elemType); CORINFO_CLASS_HANDLE (* getDefaultEqualityComparerClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE elemType); - void (* expandRawHandleIntrinsic)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult); + void (* expandRawHandleIntrinsic)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult); bool (* isIntrinsicType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE classHnd); CorInfoCallConvExtension (* getUnmanagedCallConv)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig, bool* pSuppressGCTransition); bool (* pInvokeMarshalingRequired)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig); @@ -80,8 +80,8 @@ struct JitInterfaceCallbacks bool (* isObjectImmutable)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE objPtr); bool (* getStringChar)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE strObj, int index, uint16_t* value); CORINFO_CLASS_HANDLE (* getObjectType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE objPtr); - bool (* getReadyToRunHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup); - void (* getReadyToRunDelegateCtorHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, unsigned int targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP* pLookup); + bool (* getReadyToRunHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup); + void (* getReadyToRunDelegateCtorHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, unsigned int targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup); 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); @@ -146,7 +146,7 @@ struct JitInterfaceCallbacks CORINFO_CLASS_HANDLE (* embedClassHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE handle, void** ppIndirection); CORINFO_METHOD_HANDLE (* embedMethodHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE handle, void** ppIndirection); CORINFO_FIELD_HANDLE (* embedFieldHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE handle, void** ppIndirection); - void (* embedGenericHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, CORINFO_GENERICHANDLE_RESULT* pResult); + void (* embedGenericHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult); void (* getLocationOfThisType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* pLookupKind); void (* getAddressOfPInvokeTarget)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup); void* (* GetCookieForPInvokeCalliSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* szMetaSig, void** ppIndirection); @@ -390,10 +390,11 @@ class JitInterfaceWrapper : public ICorJitInfo virtual void expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { CorInfoExceptionClass* pException = nullptr; - _callbacks->expandRawHandleIntrinsic(_thisHandle, &pException, pResolvedToken, pResult); + _callbacks->expandRawHandleIntrinsic(_thisHandle, &pException, pResolvedToken, callerHandle, pResult); if (pException != nullptr) throw pException; } @@ -875,10 +876,11 @@ class JitInterfaceWrapper : public ICorJitInfo CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->getReadyToRunHelper(_thisHandle, &pException, pResolvedToken, pGenericLookupKind, id, pLookup); + bool temp = _callbacks->getReadyToRunHelper(_thisHandle, &pException, pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup); if (pException != nullptr) throw pException; return temp; } @@ -887,10 +889,11 @@ class JitInterfaceWrapper : public ICorJitInfo CORINFO_RESOLVED_TOKEN* pTargetMethod, unsigned int targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { CorInfoExceptionClass* pException = nullptr; - _callbacks->getReadyToRunDelegateCtorHelper(_thisHandle, &pException, pTargetMethod, targetConstraint, delegateType, pLookup); + _callbacks->getReadyToRunDelegateCtorHelper(_thisHandle, &pException, pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); if (pException != nullptr) throw pException; } @@ -1506,10 +1509,11 @@ class JitInterfaceWrapper : public ICorJitInfo virtual void embedGenericHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { CorInfoExceptionClass* pException = nullptr; - _callbacks->embedGenericHandle(_thisHandle, &pException, pResolvedToken, fEmbedParent, pResult); + _callbacks->embedGenericHandle(_thisHandle, &pException, pResolvedToken, fEmbedParent, callerHandle, pResult); if (pException != nullptr) throw pException; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 4ebff96e78ab55..ffd657bea503f0 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -423,9 +423,16 @@ struct Agnostic_CheckMethodModifier struct Agnostic_EmbedGenericHandle { Agnostic_CORINFO_RESOLVED_TOKEN ResolvedToken; + DWORDLONG hCallerHandle; DWORD fEmbedParent; }; +struct Agnostic_ExpandRawHandleIntrinsic +{ + Agnostic_CORINFO_RESOLVED_TOKEN ResolvedToken; + DWORDLONG hCallerHandle; +}; + struct Agnostic_CORINFO_GENERICHANDLE_RESULT { Agnostic_CORINFO_LOOKUP lookup; @@ -687,6 +694,7 @@ struct GetReadyToRunHelper_TOKENin Agnostic_CORINFO_RESOLVED_TOKEN ResolvedToken; Agnostic_CORINFO_LOOKUP_KIND GenericLookupKind; DWORD id; + DWORDLONG callerHandle; }; struct GetReadyToRunHelper_TOKENout @@ -700,6 +708,7 @@ struct GetReadyToRunDelegateCtorHelper_TOKENIn Agnostic_CORINFO_RESOLVED_TOKEN TargetMethod; mdToken targetConstraint; DWORDLONG delegateType; + DWORDLONG callerHandle; }; struct Agnostic_RecordRelocation diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index 427c43c8ee7f21..c3445291eeb931 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -147,7 +147,7 @@ LWM(InitClass, Agnostic_InitClass, DWORD) LWM(IsDelegateCreationAllowed, DLDL, DWORD) LWM(IsFieldStatic, DWORDLONG, DWORD) LWM(GetArrayOrStringLength, DWORDLONG, DWORD) -LWM(ExpandRawHandleIntrinsic, Agnostic_CORINFO_RESOLVED_TOKENin, Agnostic_CORINFO_GENERICHANDLE_RESULT) +LWM(ExpandRawHandleIntrinsic, Agnostic_ExpandRawHandleIntrinsic, Agnostic_CORINFO_GENERICHANDLE_RESULT) LWM(IsIntrinsicType, DWORDLONG, DWORD) LWM(IsSDArray, DWORDLONG, DWORD) LWM(GetStringLiteral, DLDDD, DD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index ce889ee44cf9b6..6b5931a826374c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -1670,14 +1670,15 @@ void MethodContext::repGetCallInfoFromMethodHandle(CORINFO_METHOD_HANDLE methodH LogException(EXCEPTIONCODE_MC, "Didn't find key %016" PRIX64 ".", methodHandle); } -void MethodContext::recExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult) +void MethodContext::recExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { if (ExpandRawHandleIntrinsic == nullptr) - ExpandRawHandleIntrinsic = new LightWeightMap; + ExpandRawHandleIntrinsic = new LightWeightMap; - Agnostic_CORINFO_RESOLVED_TOKENin key; + Agnostic_ExpandRawHandleIntrinsic key; ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken); + key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, ExpandRawHandleIntrinsic); + key.hCallerHandle = CastHandle(callerHandle); Agnostic_CORINFO_GENERICHANDLE_RESULT value; value.lookup = SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(&pResult->lookup); @@ -1687,19 +1688,21 @@ void MethodContext::recExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolve ExpandRawHandleIntrinsic->Add(key, value); DEBUG_REC(dmpExpandRawHandleIntrinsic(key, value)); } -void MethodContext::dmpExpandRawHandleIntrinsic(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const Agnostic_CORINFO_GENERICHANDLE_RESULT& result) +void MethodContext::dmpExpandRawHandleIntrinsic(const Agnostic_ExpandRawHandleIntrinsic& key, const Agnostic_CORINFO_GENERICHANDLE_RESULT& result) { printf("ExpandRawHandleIntrinsic key: %s, value %s cth-%016" PRIx64 " ht-%u", - SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENin(key).c_str(), + SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ResolvedToken).c_str(), SpmiDumpHelper::DumpAgnostic_CORINFO_LOOKUP(result.lookup).c_str(), result.compileTimeHandle, result.handleType); } -void MethodContext::repExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult) +void MethodContext::repExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { - Agnostic_CORINFO_RESOLVED_TOKENin key; + Agnostic_ExpandRawHandleIntrinsic key; ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken); + + key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, ExpandRawHandleIntrinsic); + key.hCallerHandle = CastHandle(callerHandle); Agnostic_CORINFO_GENERICHANDLE_RESULT value = LookupByKeyOrMiss(ExpandRawHandleIntrinsic, key, ": key %x", pResolvedToken->token); @@ -2273,6 +2276,7 @@ CORINFO_CLASS_HANDLE MethodContext::repGetObjectType(CORINFO_OBJECT_HANDLE objPt void MethodContext::recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup, bool result) { @@ -2284,6 +2288,7 @@ void MethodContext::recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToke key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetReadyToRunHelper); key.GenericLookupKind = SpmiRecordsHelper::CreateAgnostic_CORINFO_LOOKUP_KIND(pGenericLookupKind); key.id = (DWORD)id; + key.callerHandle = CastHandle(callerHandle); GetReadyToRunHelper_TOKENout value; value.Lookup = SpmiRecordsHelper::StoreAgnostic_CORINFO_CONST_LOOKUP(pLookup); value.result = result; @@ -2304,6 +2309,7 @@ void MethodContext::dmpGetReadyToRunHelper(GetReadyToRunHelper_TOKENin key, GetR bool MethodContext::repGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { AssertMapExistsNoMessage(GetReadyToRunHelper); @@ -2313,6 +2319,7 @@ bool MethodContext::repGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToke key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetReadyToRunHelper); key.GenericLookupKind = SpmiRecordsHelper::CreateAgnostic_CORINFO_LOOKUP_KIND(pGenericLookupKind); key.id = (DWORD)id; + key.callerHandle = CastHandle(callerHandle); GetReadyToRunHelper_TOKENout value = LookupByKeyOrMissNoMessage(GetReadyToRunHelper, key); @@ -2325,6 +2332,7 @@ bool MethodContext::repGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToke void MethodContext::recGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { if (GetReadyToRunDelegateCtorHelper == nullptr) @@ -2337,6 +2345,7 @@ void MethodContext::recGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* p SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pTargetMethod, GetReadyToRunDelegateCtorHelper); key.targetConstraint = targetConstraint; key.delegateType = CastHandle(delegateType); + key.callerHandle = CastHandle(callerHandle); Agnostic_CORINFO_LOOKUP value = SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(pLookup); GetReadyToRunDelegateCtorHelper->Add(key, value); DEBUG_REC(dmpGetReadyToRunDelegateCtorHelper(key, value)); @@ -2353,6 +2362,7 @@ void MethodContext::dmpGetReadyToRunDelegateCtorHelper(GetReadyToRunDelegateCtor void MethodContext::repGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { AssertMapExistsNoMessage(GetReadyToRunDelegateCtorHelper); @@ -2363,6 +2373,7 @@ void MethodContext::repGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* p SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pTargetMethod, GetReadyToRunDelegateCtorHelper); key.targetConstraint = targetConstraint; key.delegateType = CastHandle(delegateType); + key.callerHandle = CastHandle(callerHandle); Agnostic_CORINFO_LOOKUP value = LookupByKeyOrMissNoMessage(GetReadyToRunDelegateCtorHelper, key); @@ -3101,6 +3112,7 @@ CorInfoHelpFunc MethodContext::repGetNewHelper(CORINFO_CLASS_HANDLE classHandle void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { if (EmbedGenericHandle == nullptr) @@ -3110,6 +3122,7 @@ void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolve ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, EmbedGenericHandle); key.fEmbedParent = (DWORD)fEmbedParent; + key.hCallerHandle = CastHandle(callerHandle); Agnostic_CORINFO_GENERICHANDLE_RESULT value; value.lookup = SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(&pResult->lookup); @@ -3131,6 +3144,7 @@ void MethodContext::dmpEmbedGenericHandle(const Agnostic_EmbedGenericHandle& } void MethodContext::repEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { AssertMapExistsNoMessage(EmbedGenericHandle); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 5a107c8020c1c6..cf9c235ae987ea 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -272,9 +272,9 @@ class MethodContext void dmpIsSDArray(DWORDLONG key, DWORD value); bool repIsSDArray(CORINFO_CLASS_HANDLE cls); - void recExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult); - void dmpExpandRawHandleIntrinsic(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const Agnostic_CORINFO_GENERICHANDLE_RESULT& result); - void repExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult); + void recExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult); + void dmpExpandRawHandleIntrinsic(const Agnostic_ExpandRawHandleIntrinsic& key, const Agnostic_CORINFO_GENERICHANDLE_RESULT& result); + void repExpandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult); void recIsIntrinsicType(CORINFO_CLASS_HANDLE cls, bool result); void dmpIsIntrinsicType(DWORDLONG key, DWORD value); @@ -315,23 +315,27 @@ class MethodContext void recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup, bool result); void dmpGetReadyToRunHelper(GetReadyToRunHelper_TOKENin key, GetReadyToRunHelper_TOKENout value); bool repGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup); void recGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup); void dmpGetReadyToRunDelegateCtorHelper(GetReadyToRunDelegateCtorHelper_TOKENIn key, Agnostic_CORINFO_LOOKUP pLookup); void repGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup); void recGetHelperFtn(CorInfoHelpFunc ftnNum, void** ppIndirection, void* result); @@ -423,11 +427,13 @@ class MethodContext void recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult); void dmpEmbedGenericHandle(const Agnostic_EmbedGenericHandle& key, const Agnostic_CORINFO_GENERICHANDLE_RESULT& value); void repEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult); void recGetEHinfo(CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, CORINFO_EH_CLAUSE* clause); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 2c80a2ea0e953c..d53002a42914b1 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -259,11 +259,12 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getDefaultEqualityComparerClass(CORINFO_C } void interceptor_ICJI::expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { mc->cr->AddCall("expandRawHandleIntrinsic"); - original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult); - mc->recExpandRawHandleIntrinsic(pResolvedToken, pResult); + original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, callerHandle, pResult); + mc->recExpandRawHandleIntrinsic(pResolvedToken, callerHandle, pResult); } // Is the given type in System.Private.Corelib and marked with IntrinsicAttribute? @@ -780,22 +781,24 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType(CORINFO_OBJECT_HANDLE typeO bool interceptor_ICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { mc->cr->AddCall("getReadyToRunHelper"); - bool result = original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup); - mc->recGetReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup, result); + bool result = original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup); + mc->recGetReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup, result); return result; } void interceptor_ICJI::getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { mc->cr->AddCall("getReadyToRunDelegateCtorHelper"); - original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, pLookup); - mc->recGetReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, pLookup); + original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); + mc->recGetReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); } // This function tries to initialize the class (run the class constructor). @@ -1530,11 +1533,12 @@ CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle(CORINFO_FIELD_HANDLE han void interceptor_ICJI::embedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, // TRUE - embeds parent type handle of the field/method // handle + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { mc->cr->AddCall("embedGenericHandle"); - original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult); - mc->recEmbedGenericHandle(pResolvedToken, fEmbedParent, pResult); + original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, callerHandle, pResult); + mc->recEmbedGenericHandle(pResolvedToken, fEmbedParent, callerHandle, pResult); } // Return information used to locate the exact enclosing type of the current method. 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 952ba22c1c2106..ef1b277e805333 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -171,10 +171,11 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getDefaultEqualityComparerClass( void interceptor_ICJI::expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { mcs->AddCall("expandRawHandleIntrinsic"); - original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult); + original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, callerHandle, pResult); } bool interceptor_ICJI::isIntrinsicType( @@ -564,20 +565,22 @@ bool interceptor_ICJI::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { mcs->AddCall("getReadyToRunHelper"); - return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup); + return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup); } void interceptor_ICJI::getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { mcs->AddCall("getReadyToRunDelegateCtorHelper"); - original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, pLookup); + original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); } CorInfoInitClassResult interceptor_ICJI::initClass( @@ -1091,10 +1094,11 @@ CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle( void interceptor_ICJI::embedGenericHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { mcs->AddCall("embedGenericHandle"); - original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult); + original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, callerHandle, pResult); } void interceptor_ICJI::getLocationOfThisType( 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 99a89269c0a429..55aef651273476 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -152,9 +152,10 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getDefaultEqualityComparerClass( void interceptor_ICJI::expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN* pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { - original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult); + original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, callerHandle, pResult); } bool interceptor_ICJI::isIntrinsicType( @@ -495,18 +496,20 @@ bool interceptor_ICJI::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { - return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup); + return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup); } void interceptor_ICJI::getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { - original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, pLookup); + original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); } CorInfoInitClassResult interceptor_ICJI::initClass( @@ -956,9 +959,10 @@ CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle( void interceptor_ICJI::embedGenericHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { - original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult); + original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, callerHandle, pResult); } void interceptor_ICJI::getLocationOfThisType( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 79254788ae2c4f..f23c8e12f86618 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -221,10 +221,10 @@ CORINFO_CLASS_HANDLE MyICJI::getDefaultEqualityComparerClass(CORINFO_CLASS_HANDL return result; } -void MyICJI::expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult) +void MyICJI::expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { jitInstance->mc->cr->AddCall("expandRawHandleIntrinsic"); - jitInstance->mc->repExpandRawHandleIntrinsic(pResolvedToken, pResult); + jitInstance->mc->repExpandRawHandleIntrinsic(pResolvedToken, callerHandle, pResult); } // Is the given type in System.Private.Corelib and marked with IntrinsicAttribute? @@ -653,19 +653,21 @@ CORINFO_CLASS_HANDLE MyICJI::getObjectType(CORINFO_OBJECT_HANDLE objPtr) bool MyICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP* pLookup) { jitInstance->mc->cr->AddCall("getReadyToRunHelper"); - return jitInstance->mc->repGetReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup); + return jitInstance->mc->repGetReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, callerHandle, pLookup); } void MyICJI::getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* pLookup) { jitInstance->mc->cr->AddCall("getReadyToRunDelegateCtorHelper"); - jitInstance->mc->repGetReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, pLookup); + jitInstance->mc->repGetReadyToRunDelegateCtorHelper(pTargetMethod, targetConstraint, delegateType, callerHandle, pLookup); } // This function tries to initialize the class (run the class constructor). @@ -1338,10 +1340,11 @@ CORINFO_FIELD_HANDLE MyICJI::embedFieldHandle(CORINFO_FIELD_HANDLE handle, void* // void MyICJI::embedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, // TRUE - embeds parent type handle of the field/method handle + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT* pResult) { jitInstance->mc->cr->AddCall("embedGenericHandle"); - jitInstance->mc->repEmbedGenericHandle(pResolvedToken, fEmbedParent, pResult); + jitInstance->mc->repEmbedGenericHandle(pResolvedToken, fEmbedParent, callerHandle, pResult); } // Return information used to locate the exact enclosing type of the current method. diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 438c6e1bef8923..05d9365e967964 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -2823,6 +2823,7 @@ void CEEInfo::MethodCompileComplete(CORINFO_METHOD_HANDLE methHnd) void CEEInfo::embedGenericHandle( CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fEmbedParent, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT *pResult) { CONTRACTL { @@ -2925,6 +2926,7 @@ void CEEInfo::embedGenericHandle( pResolvedToken, NULL, pTemplateMD, + GetMethod(callerHandle), &pResult->lookup); } else @@ -3022,7 +3024,7 @@ MethodDesc * CEEInfo::GetMethodForSecurity(CORINFO_METHOD_HANDLE callerHandle) return m_pMethodForSecurity_Value; } - MethodDesc * pCallerMethod = (MethodDesc *)callerHandle; + MethodDesc * pCallerMethod = GetMethod(callerHandle); //If the caller is generic, load the open type and then load the field again, This allows us to //differentiate between BadGeneric containing a memberRef for a field of type InaccessibleClass and @@ -3095,6 +3097,7 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, MethodDesc * pTemplateMD /* for method-based slots */, + MethodDesc * pCallerMD, CORINFO_LOOKUP *pResultLookup) { CONTRACTL{ @@ -3102,6 +3105,8 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr PRECONDITION(CheckPointer(pResultLookup)); } CONTRACTL_END; + _ASSERT(pCallerMD != nullptr); + pResultLookup->lookupKind.needsRuntimeLookup = true; pResultLookup->lookupKind.runtimeLookupFlags = 0; @@ -3117,16 +3122,8 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr // Unless we decide otherwise, just do the lookup via a helper function pResult->indirections = CORINFO_USEHELPER; - // Runtime lookups in inlined contexts are not supported by the runtime for now - if (pResolvedToken->tokenContext != METHOD_BEING_COMPILED_CONTEXT()) - { - pResultLookup->lookupKind.runtimeLookupKind = CORINFO_LOOKUP_NOT_SUPPORTED; - return; - } - - MethodDesc* pContextMD = GetMethodFromContext(pResolvedToken->tokenContext); + MethodDesc* pContextMD = pCallerMD; MethodTable* pContextMT = pContextMD->GetMethodTable(); - bool isStaticVirtual = (pConstrainedResolvedToken != nullptr && pContextMD != nullptr && pContextMD->IsStatic()); // There is a pathological case where invalid IL refereces __Canon type directly, but there is no dictionary availabled to store the lookup. if (!pContextMD->IsSharedByGenericInstantiations()) @@ -5289,19 +5286,6 @@ void CEEInfo::getCallInfo( { pResult->exactContextNeedsRuntimeLookup = TRUE; } - - // Use main method as the context as long as the methods are called on the same type - if (pResult->exactContextNeedsRuntimeLookup && - pResolvedToken->tokenContext == METHOD_BEING_COMPILED_CONTEXT() && - constrainedType.IsNull() && - exactType == m_pMethodBeingCompiled->GetMethodTable() && - ((pResolvedToken->cbTypeSpec == 0) || IsTypeSpecForTypicalInstantiation(SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec)))) - { - // The typespec signature should be only missing for dynamic methods - _ASSERTE((pResolvedToken->cbTypeSpec != 0) || m_pMethodBeingCompiled->IsDynamicMethod()); - - pResult->contextHandle = METHOD_BEING_COMPILED_CONTEXT(); - } } // @@ -5453,6 +5437,7 @@ void CEEInfo::getCallInfo( pResolvedToken, pConstrainedResolvedToken, pMD, + GetMethod(callerHandle), &pResult->codePointerLookup); } else @@ -5504,6 +5489,7 @@ void CEEInfo::getCallInfo( pResolvedToken, pConstrainedResolvedToken, pMD, + GetMethod(callerHandle), &pResult->stubLookup); } else @@ -5545,7 +5531,7 @@ void CEEInfo::getCallInfo( pResult->hMethod = CORINFO_METHOD_HANDLE(pTargetMD); pResult->accessAllowed = CORINFO_ACCESS_ALLOWED; - MethodDesc* callerMethod = (MethodDesc*)callerHandle; + MethodDesc* callerMethod = GetMethod(callerHandle); if ((flags & CORINFO_CALLINFO_SECURITYCHECKS) && RequiresAccessCheck(pResolvedToken->tokenScope)) { @@ -6319,6 +6305,7 @@ bool CEEInfo::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_CONST_LOOKUP * pLookup ) { @@ -6331,7 +6318,8 @@ void CEEInfo::getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, - CORINFO_LOOKUP * pLookup + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_LOOKUP * pLookup ) { LIMITED_METHOD_CONTRACT; @@ -8964,6 +8952,7 @@ CORINFO_METHOD_HANDLE CEEInfo::getUnboxedEntry( /*********************************************************************/ void CEEInfo::expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, CORINFO_GENERICHANDLE_RESULT * pResult) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index bbca5c355fbb97..9b307983a24d0c 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -558,6 +558,7 @@ class CEEInfo : public ICorJitInfo CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken /* for ConstrainedMethodEntrySlot */, MethodDesc * pTemplateMD /* for method-based slots */, + MethodDesc * pCallerMD, CORINFO_LOOKUP *pResultLookup); #if defined(FEATURE_GDBJIT)