Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate code manager for the interpreter #112985

Merged
merged 16 commits into from
Mar 22, 2025
6 changes: 5 additions & 1 deletion src/coreclr/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,12 @@ HRESULT ClrDataAccess::EnumMemDumpJitManagerInfo(IN CLRDataEnumMemoryFlags flags

if (flags == CLRDATA_ENUM_MEM_HEAP2)
{
EEJitManager* managerPtr = ExecutionManager::GetEEJitManager();
EECodeGenManager* managerPtr = ExecutionManager::GetEEJitManager();
managerPtr->EnumMemoryRegions(flags);
#ifdef FEATURE_INTERPRETER
managerPtr = ExecutionManager::GetInterpreterJitManager();
managerPtr->EnumMemoryRegions(flags);
#endif // FEATURE_INTERPRETER
}

return status;
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,12 @@ RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitOs, W("AltJitOS"), "Sets target OS for
RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitExcludeAssemblies, W("AltJitExcludeAssemblies"), "Do not use AltJit on this semicolon-delimited list of assemblies.")
#endif // defined(ALLOW_SXS_JIT)

#ifdef FEATURE_INTERPRETER
RETAIL_CONFIG_STRING_INFO(EXTERNAL_InterpreterName, W("InterpreterName"), "Primary interpreter to use")
CONFIG_STRING_INFO(INTERNAL_InterpreterPath, W("InterpreterPath"), "Full path to the interpreter to use")
RETAIL_CONFIG_STRING_INFO(EXTERNAL_Interpreter, W("Interpreter"), "Enables Interpreter and selectively limits it to the specified methods.")
#endif // FEATURE_INTERPRETER

RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitHostMaxSlabCache, W("JitHostMaxSlabCache"), 0x1000000, "Sets jit host max slab cache size, 16MB default")

RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitOptimizeType, W("JitOptimizeType"), 0 /* OPT_DEFAULT */, "")
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ DEFINE_DACVAR(PTR_EEJitManager, ExecutionManager__m_pEEJitManager, ExecutionMana
#ifdef FEATURE_READYTORUN
DEFINE_DACVAR(PTR_ReadyToRunJitManager, ExecutionManager__m_pReadyToRunJitManager, ExecutionManager::m_pReadyToRunJitManager)
#endif
#ifdef FEATURE_INTERPRETER
DEFINE_DACVAR(PTR_InterpreterJitManager, ExecutionManager__m_pInterpreterJitManager, ExecutionManager::m_pInterpreterJitManager)
DEFINE_DACVAR(PTR_InterpreterCodeManager, ExecutionManager__m_pInterpreterCodeMan, ExecutionManager::m_pInterpreterCodeMan)
#endif

DEFINE_DACVAR_NO_DUMP(VMHELPDEF *, dac__hlpFuncTable, ::hlpFuncTable)
DEFINE_DACVAR(VMHELPDEF *, dac__hlpDynamicFuncTable, ::hlpDynamicFuncTable)
Expand Down
241 changes: 209 additions & 32 deletions src/coreclr/inc/eetwain.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,6 @@ virtual bool IsGcSafe(EECodeInfo *pCodeInfo,
virtual bool HasTailCalls(EECodeInfo *pCodeInfo) = 0;
#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64

#if defined(TARGET_AMD64) && defined(_DEBUG)
/*
Locates the end of the last interruptible region in the given code range.
Returns 0 if the entire range is uninterruptible. Returns the end point
if the entire range is interruptible.
*/
virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset,
unsigned endOffset,
GCInfoToken gcInfoToken) = 0;
#endif // TARGET_AMD64 && _DEBUG

/*
Enumerate all live object references in that function using
the virtual register set. Same reference location cannot be enumerated
Expand Down Expand Up @@ -321,11 +310,6 @@ virtual unsigned int GetFrameSize(GCInfoToken gcInfoToken) = 0;
#ifndef FEATURE_EH_FUNCLETS
virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)=0;

virtual BOOL IsInFilter(GCInfoToken gcInfoToken,
unsigned offset,
PCONTEXT pCtx,
DWORD curNestLevel) = 0;

virtual BOOL LeaveFinally(GCInfoToken gcInfoToken,
unsigned offset,
PCONTEXT pCtx) = 0;
Expand Down Expand Up @@ -462,18 +446,6 @@ virtual
bool HasTailCalls(EECodeInfo *pCodeInfo);
#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || defined(TARGET_RISCV64)

#if defined(TARGET_AMD64) && defined(_DEBUG)
/*
Locates the end of the last interruptible region in the given code range.
Returns 0 if the entire range is uninterruptible. Returns the end point
if the entire range is interruptible.
*/
virtual
unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset,
unsigned endOffset,
GCInfoToken gcInfoToken);
#endif // TARGET_AMD64 && _DEBUG

/*
Enumerate all live object references in that function using
the virtual register set. Same reference location cannot be enumerated
Expand Down Expand Up @@ -588,10 +560,6 @@ unsigned int GetFrameSize(GCInfoToken gcInfoToken);

#ifndef FEATURE_EH_FUNCLETS
virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg);
virtual BOOL IsInFilter(GCInfoToken gcInfoToken,
unsigned offset,
PCONTEXT pCtx,
DWORD curNestLevel);
virtual BOOL LeaveFinally(GCInfoToken gcInfoToken,
unsigned offset,
PCONTEXT pCtx);
Expand Down Expand Up @@ -646,6 +614,215 @@ struct CodeManStateBuf

#endif

#ifdef FEATURE_INTERPRETER

class InterpreterCodeManager : public ICodeManager {

VPTR_VTABLE_CLASS_AND_CTOR(InterpreterCodeManager, ICodeManager)

public:


#ifndef DACCESS_COMPILE
#ifndef FEATURE_EH_FUNCLETS
virtual
void FixContext(ContextType ctxType,
EHContext *ctx,
EECodeInfo *pCodeInfo,
DWORD dwRelOffset,
DWORD nestingLevel,
OBJECTREF thrownObject,
CodeManState *pState,
size_t ** ppShadowSP, // OUT
size_t ** ppEndRegion) // OUT
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
}
#endif // !FEATURE_EH_FUNCLETS
#endif // !DACCESS_COMPILE

#ifdef TARGET_X86
/*
Gets the ambient stack pointer value at the given nesting level within
the method.
*/
virtual
TADDR GetAmbientSP(PREGDISPLAY pContext,
EECodeInfo *pCodeInfo,
DWORD dwRelOffset,
DWORD nestingLevel,
CodeManState *pState)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return NULL;
}
#endif // TARGET_X86

virtual
ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return 0;
}

virtual
bool UnwindStackFrame(
PREGDISPLAY pContext,
EECodeInfo *pCodeInfo,
unsigned flags,
CodeManState *pState);

virtual
bool IsGcSafe( EECodeInfo *pCodeInfo,
DWORD dwRelOffset);

#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
virtual
bool HasTailCalls(EECodeInfo *pCodeInfo)
{
_ASSERTE(FALSE);
return false;
}
#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || defined(TARGET_RISCV64)

virtual
bool EnumGcRefs(PREGDISPLAY pContext,
EECodeInfo *pCodeInfo,
unsigned flags,
GCEnumCallback pCallback,
LPVOID hCallBack,
DWORD relOffsetOverride = NO_OVERRIDE_OFFSET);

virtual
OBJECTREF GetInstance(
PREGDISPLAY pContext,
EECodeInfo * pCodeInfo);

virtual
PTR_VOID GetParamTypeArg(PREGDISPLAY pContext,
EECodeInfo * pCodeInfo);

virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext,
EECodeInfo * pCodeInfo);

virtual
void * GetGSCookieAddr(PREGDISPLAY pContext,
EECodeInfo * pCodeInfo,
unsigned flags,
CodeManState * pState)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return NULL;
}


#ifndef USE_GC_INFO_DECODER
virtual
bool IsInPrologOrEpilog(
DWORD relOffset,
GCInfoToken gcInfoToken,
size_t* prologSize)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return false;
}

virtual
bool IsInSynchronizedRegion(
DWORD relOffset,
GCInfoToken gcInfoToken,
unsigned flags)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return false;
}
#endif // !USE_GC_INFO_DECODER

virtual
size_t GetFunctionSize(GCInfoToken gcInfoToken);

virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken X86_ARG(ReturnKind * returnKind))
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return false;
}

#ifndef USE_GC_INFO_DECODER

virtual
unsigned int GetFrameSize(GCInfoToken gcInfoToken)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return 0;
}
#endif // USE_GC_INFO_DECODER

#ifndef DACCESS_COMPILE

#ifndef FEATURE_EH_FUNCLETS
virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return NULL;
}

virtual BOOL LeaveFinally(GCInfoToken gcInfoToken,
unsigned offset,
PCONTEXT pCtx)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
return FALSE;
}

virtual void LeaveCatch(GCInfoToken gcInfoToken,
unsigned offset,
PCONTEXT pCtx)
{
// Interpreter-TODO: Implement this if needed
_ASSERTE(FALSE);
}
#endif // FEATURE_EH_FUNCLETS

#ifdef FEATURE_REMAP_FUNCTION

virtual
HRESULT FixContextForEnC(PCONTEXT pCtx,
EECodeInfo * pOldCodeInfo,
const ICorDebugInfo::NativeVarInfo * oldMethodVars,
SIZE_T oldMethodVarsCount,
EECodeInfo * pNewCodeInfo,
const ICorDebugInfo::NativeVarInfo * newMethodVars,
SIZE_T newMethodVarsCount)
{
// Interpreter-TODO: Implement this
_ASSERTE(FALSE);
return E_NOTIMPL;
}
#endif // FEATURE_REMAP_FUNCTION

#endif // !DACCESS_COMPILE

#ifdef DACCESS_COMPILE
virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
{
// Nothing to do
}
#endif

};

#endif // FEATURE_INTERPRETER

//*****************************************************************************
#endif // _EETWAIN_H
//*****************************************************************************
4 changes: 4 additions & 0 deletions src/coreclr/inc/vptr_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ VPTR_CLASS(EEJitManager)
#ifdef FEATURE_READYTORUN
VPTR_CLASS(ReadyToRunJitManager)
#endif
#ifdef FEATURE_INTERPRETER
VPTR_CLASS(InterpreterJitManager)
VPTR_CLASS(InterpreterCodeManager)
#endif
VPTR_CLASS(EECodeManager)

VPTR_CLASS(RangeList)
Expand Down
9 changes: 2 additions & 7 deletions src/coreclr/interpreter/eeinterp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ CorJitResult CILInterp::compileMethod(ICorJitInfo* compHnd,

// TODO: replace this by something like the JIT does to support multiple methods being specified and we don't
// keep fetching it on each call to compileMethod
const char *methodToInterpret = g_interpHost->getStringConfigValue("AltJit");
const char *methodToInterpret = g_interpHost->getStringConfigValue("Interpreter");
doInterpret = (methodName != NULL && strcmp(methodName, methodToInterpret) == 0);
g_interpHost->freeStringConfigValue(methodToInterpret);
if (doInterpret)
Expand All @@ -90,9 +90,7 @@ CorJitResult CILInterp::compileMethod(ICorJitInfo* compHnd,
uint32_t sizeOfCode = sizeof(InterpMethod*) + IRCodeSize * sizeof(int32_t);
uint8_t unwindInfo[8] = {0, 0, 0, 0, 0, 0, 0, 0};

// TODO: get rid of the need to allocate fake unwind info.
compHnd->reserveUnwindInfo(false /* isFunclet */, false /* isColdCode */ , sizeof(unwindInfo) /* unwindSize */);
AllocMemArgs args;
AllocMemArgs args {};
args.hotCodeSize = sizeOfCode;
args.coldCodeSize = 0;
args.roDataSize = 0;
Expand All @@ -104,9 +102,6 @@ CorJitResult CILInterp::compileMethod(ICorJitInfo* compHnd,
*(InterpMethod**)args.hotCodeBlockRW = pMethod;
memcpy ((uint8_t*)args.hotCodeBlockRW + sizeof(InterpMethod*), pIRCode, IRCodeSize * sizeof(int32_t));

// TODO: get rid of the need to allocate fake unwind info
compHnd->allocUnwindInfo((uint8_t*)args.hotCodeBlock, (uint8_t*)args.coldCodeBlock, 0, 1, sizeof(unwindInfo), unwindInfo, CORJIT_FUNC_ROOT);

*entryAddress = (uint8_t*)args.hotCodeBlock;
*nativeSizeOfCode = sizeOfCode;

Expand Down
Loading
Loading