diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 139779b6a05b18..d61bf5fbe81840 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -1072,6 +1072,50 @@ void InterpCompiler::BuildGCInfo(InterpMethod *pInterpMethod) gcInfoEncoder->SetCodeLength(ConvertOffset(m_methodCodeSize)); + GENERIC_CONTEXTPARAM_TYPE paramType; + + switch (m_methodInfo->options & CORINFO_GENERICS_CTXT_MASK) + { + case CORINFO_GENERICS_CTXT_FROM_METHODDESC: + paramType = GENERIC_CONTEXTPARAM_MD; + break; + case CORINFO_GENERICS_CTXT_FROM_METHODTABLE: + paramType = GENERIC_CONTEXTPARAM_MT; + break; + case CORINFO_GENERICS_CTXT_FROM_THIS: + case 0: + paramType = GENERIC_CONTEXTPARAM_NONE; + break; + default: + paramType = GENERIC_CONTEXTPARAM_NONE; + assert(!"Unexpected generic context parameter type"); + break; + } + + gcInfoEncoder->SetSizeOfStackOutgoingAndScratchArea(0); + + if (m_compHnd->getMethodAttribs(m_methodInfo->ftn) & CORINFO_FLG_SHAREDINST) + { + if ((m_methodInfo->options & CORINFO_GENERICS_CTXT_MASK) != CORINFO_GENERICS_CTXT_FROM_THIS) + { + assert(paramType != GENERIC_CONTEXTPARAM_NONE); + + int32_t genericArgStackOffset = m_pVars[getParamArgIndex()].offset; + INTERP_DUMP("SetGenericsInstContextStackSlot at %u\n", (unsigned)genericArgStackOffset); + gcInfoEncoder->SetPrologSize(4); // Size of 1 instruction + gcInfoEncoder->SetStackBaseRegister(0); + gcInfoEncoder->SetGenericsInstContextStackSlot(genericArgStackOffset, paramType); + } + else + { + assert((paramType == GENERIC_CONTEXTPARAM_NONE)); + } + } + else + { + assert((paramType == GENERIC_CONTEXTPARAM_NONE)); + } + INTERP_DUMP("Allocating gcinfo slots for %u vars\n", m_varsSize); for (int pass = 0; pass < 2; pass++) diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index d7ca7435689aee..d305db445aca8d 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -3358,6 +3358,63 @@ PTR_EXCEPTION_CLAUSE_TOKEN EECodeGenManager::GetNextEHClause(EH_CLAUSE_ENUMERATO } #ifndef DACCESS_COMPILE + +#ifdef FEATURE_INTERPRETER +TypeHandle InterpreterJitManager::ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause, + CrawlFrame *pCf) +{ + // We don't want to use a runtime contract here since this codepath is used during + // the processing of a hard SO. Contracts use a significant amount of stack + // which we can't afford for those cases. + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_TRIGGERS; + + TypeHandle thResolved = EECodeGenManager::ResolveEHClause(pEHClause, pCf); + + if (thResolved.IsSharedByGenericInstantiations()) + { + _ASSERTE(!HasCachedTypeHandle(pEHClause)); + + GenericParamContextType paramContextType = pCf->GetCodeManager()->GetParamContextType(pCf->GetRegisterSet(), pCf->GetCodeInfo()); + _ASSERTE(SafeToReportGenericParamContext(pCf)); + if (SafeToReportGenericParamContext(pCf)) + { + MethodDesc *pMD = pCf->GetFunction(); + TypeHandle declaringType = (TypeHandle)pMD->GetMethodTable(); + + // Handle the case where the method is a static shared generic method and we need to keep the type + // of the generic parameters alive + if (paramContextType == GENERIC_PARAM_CONTEXT_METHODDESC) + { + pMD = dac_cast(pCf->GetParamTypeArg()); + declaringType = (TypeHandle)pMD->GetMethodTable(); + } + else if (paramContextType == GENERIC_PARAM_CONTEXT_METHODTABLE) + { + declaringType = (TypeHandle)dac_cast(pCf->GetParamTypeArg()); + } + else + { + _ASSERTE(paramContextType == GENERIC_PARAM_CONTEXT_THIS); + GCX_COOP(); + declaringType = (TypeHandle)dac_cast(pCf->GetExactGenericArgsToken()); + } + + _ASSERTE(!declaringType.IsNull()); + + SigTypeContext typeContext(pMD, declaringType); + + Module* pModule = pMD->GetModule(); + + thResolved = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, pEHClause->ClassToken, &typeContext, + ClassLoader::ReturnNullIfNotFound); + } + } + + return thResolved; +} +#endif // FEATURE_INTERPRETER + TypeHandle EECodeGenManager::ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause, CrawlFrame *pCf) { diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index 63cc4daa05da45..8d4c3fb425f4fb 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -2795,6 +2795,11 @@ class InterpreterJitManager final : public EECodeGenManager OUT ICorDebugInfo::RichOffsetMapping** ppRichMappings, OUT ULONG32* pNumRichMappings); +#ifndef DACCESS_COMPILE + virtual TypeHandle ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause, + CrawlFrame *pCf); +#endif // #ifndef DACCESS_COMPILE + #if defined(FEATURE_EH_FUNCLETS) virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo) { @@ -3059,4 +3064,6 @@ inline TADDR InterpreterJitManager::JitTokenToStartAddress(const METHODTOKEN& Me void ThrowOutOfMemoryWithinRange(); +bool SafeToReportGenericParamContext(CrawlFrame* pCF); + #endif // !__CODEMAN_HPP__ diff --git a/src/coreclr/vm/eetwain.cpp b/src/coreclr/vm/eetwain.cpp index e2da25b23d826f..cb9e57d5501f55 100644 --- a/src/coreclr/vm/eetwain.cpp +++ b/src/coreclr/vm/eetwain.cpp @@ -2603,22 +2603,47 @@ bool InterpreterCodeManager::EnumGcRefs(PREGDISPLAY pContext, OBJECTREF InterpreterCodeManager::GetInstance(PREGDISPLAY pContext, EECodeInfo * pCodeInfo) { - // Interpreter-TODO: Implement this - return NULL; + TADDR baseStackSlot = GetFP(pContext->pCurrentContext); + return *dac_cast(baseStackSlot); } PTR_VOID InterpreterCodeManager::GetParamTypeArg(PREGDISPLAY pContext, EECodeInfo * pCodeInfo) { - // Interpreter-TODO: Implement this + LIMITED_METHOD_DAC_CONTRACT; + + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + + InterpreterGcInfoDecoder gcInfoDecoder( + gcInfoToken, + GcInfoDecoderFlags (DECODE_GENERICS_INST_CONTEXT) + ); + + INT32 spOffsetGenericsContext = gcInfoDecoder.GetGenericsInstContextStackSlot(); + if (spOffsetGenericsContext != NO_GENERICS_INST_CONTEXT) + { + TADDR baseStackSlot = GetFP(pContext->pCurrentContext); + TADDR taSlot = (TADDR)( spOffsetGenericsContext + baseStackSlot ); + TADDR taExactGenericsToken = *PTR_TADDR(taSlot); + return PTR_VOID(taExactGenericsToken); + } return NULL; } GenericParamContextType InterpreterCodeManager::GetParamContextType(PREGDISPLAY pContext, EECodeInfo * pCodeInfo) { - // Interpreter-TODO: Implement this - return GENERIC_PARAM_CONTEXT_NONE; + MethodDesc *pMD = pCodeInfo->GetMethodDesc(); + GenericParamContextType paramContextType = GENERIC_PARAM_CONTEXT_NONE; + + if (pMD->RequiresInstMethodDescArg()) + paramContextType = GENERIC_PARAM_CONTEXT_METHODDESC; + else if (pMD->RequiresInstMethodTableArg()) + paramContextType = GENERIC_PARAM_CONTEXT_METHODTABLE; + else if (pMD->AcquiresInstMethodTableFromThis()) + paramContextType = GENERIC_PARAM_CONTEXT_THIS; + + return paramContextType; } size_t InterpreterCodeManager::GetFunctionSize(GCInfoToken gcInfoToken) diff --git a/src/coreclr/vm/gcenv.ee.common.cpp b/src/coreclr/vm/gcenv.ee.common.cpp index 0df511d2eadcbe..e4e4ac4aae092d 100644 --- a/src/coreclr/vm/gcenv.ee.common.cpp +++ b/src/coreclr/vm/gcenv.ee.common.cpp @@ -110,7 +110,7 @@ unsigned FindFirstInterruptiblePoint(CrawlFrame* pCF, unsigned offs, unsigned en // there's no context provided by the caller). // See code:getMethodSigInternal // -inline bool SafeToReportGenericParamContext(CrawlFrame* pCF) +bool SafeToReportGenericParamContext(CrawlFrame* pCF) { LIMITED_METHOD_CONTRACT;