diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index e08ffe9dd267dc..d5b2d29d2e5d5a 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -126,6 +126,8 @@ if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ add_definitions(-DFEATURE_INTEROP_DEBUGGING) endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) +add_compile_definitions($<${FEATURE_INTERPRETER}:FEATURE_INTERPRETER>) + if (CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_ISYM_READER) endif(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/clrfeatures.cmake b/src/coreclr/clrfeatures.cmake index 2bf7216af1b4db..90b40131b533d3 100644 --- a/src/coreclr/clrfeatures.cmake +++ b/src/coreclr/clrfeatures.cmake @@ -16,6 +16,14 @@ if(NOT DEFINED FEATURE_DBGIPC) endif() endif(NOT DEFINED FEATURE_DBGIPC) +if(NOT DEFINED FEATURE_INTERPRETER) + if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) + set(FEATURE_INTERPRETER $,1,0>) + else(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) + set(FEATURE_INTERPRETER 0) + endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) +endif(NOT DEFINED FEATURE_INTERPRETER) + if(NOT DEFINED FEATURE_STANDALONE_GC) set(FEATURE_STANDALONE_GC 1) endif(NOT DEFINED FEATURE_STANDALONE_GC) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 9d01304c6639d8..2128b8cabe7c32 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -786,7 +786,7 @@ enum CorInfoFlag enum CorInfoMethodRuntimeFlags { CORINFO_FLG_BAD_INLINEE = 0x00000001, // The method is not suitable for inlining - // unused = 0x00000002, + CORINFO_FLG_INTERPRETER = 0x00000002, // The method was compiled by the interpreter // unused = 0x00000004, CORINFO_FLG_SWITCHED_TO_MIN_OPT = 0x00000008, // The JIT decided to switch to MinOpt for this method, when it was not requested CORINFO_FLG_SWITCHED_TO_OPTIMIZED = 0x00000010, // The JIT decided to switch to tier 1 for this method, when a different tier was requested diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index 95714fd0757321..6c03f7c91b6992 100644 --- a/src/coreclr/vm/amd64/AsmHelpers.asm +++ b/src/coreclr/vm/amd64/AsmHelpers.asm @@ -11,6 +11,9 @@ extern ProfileLeave:proc extern ProfileTailcall:proc extern OnHijackWorker:proc extern JIT_RareDisableHelperWorker:proc +ifdef FEATURE_INTERPRETER +extern ExecuteInterpretedMethod:proc +endif extern g_pPollGC:QWORD extern g_TrapReturningThreads:DWORD @@ -458,4 +461,21 @@ JIT_PollGCRarePath: TAILJMP_RAX LEAF_END JIT_PollGC, _TEXT +ifdef FEATURE_INTERPRETER +NESTED_ENTRY InterpreterStub, _TEXT + + PROLOG_WITH_TRANSITION_BLOCK + + ; + ; call ExecuteInterpretedMethod + ; + lea rcx, [rsp + __PWTB_TransitionBlock] ; pTransitionBlock* + mov rdx, METHODDESC_REGISTER + call ExecuteInterpretedMethod + + EPILOG_WITH_TRANSITION_BLOCK_RETURN + +NESTED_END InterpreterStub, _TEXT +endif ; FEATURE_INTERPRETER + end \ No newline at end of file diff --git a/src/coreclr/vm/amd64/asmhelpers.S b/src/coreclr/vm/amd64/asmhelpers.S index 6bce2d2f2d3436..c4391a00b23c32 100644 --- a/src/coreclr/vm/amd64/asmhelpers.S +++ b/src/coreclr/vm/amd64/asmhelpers.S @@ -330,3 +330,22 @@ LOCAL_LABEL(JIT_PollGCRarePath): mov rax, [rax] jmp rax LEAF_END JIT_PollGC, _TEXT + +#ifdef FEATURE_INTERPRETER +NESTED_ENTRY InterpreterStub, _TEXT, NoHandler + + PROLOG_WITH_TRANSITION_BLOCK 8, 0, 0, 0, 0 + mov [rsp], rax // Return buffer in Swift calling convention + + # + # call ExecuteInterpretedMethod + # + lea rdi, [rsp + __PWTB_TransitionBlock] // pTransitionBlock* + mov rsi, METHODDESC_REGISTER + call C_FUNC(ExecuteInterpretedMethod) + + mov rax, [rsp] + EPILOG_WITH_TRANSITION_BLOCK_RETURN + +NESTED_END InterpreterStub, _TEXT +#endif // FEATURE_INTERPRETER diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index d40d210dfb03ad..2fa596af772ffc 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -817,3 +817,18 @@ LOCAL_LABEL(JIT_PollGCRarePath): ldr x9, [x9] br x9 LEAF_END JIT_PollGC, _TEXT + +#ifdef FEATURE_INTERPRETER +NESTED_ENTRY InterpreterStub, _TEXT, NoHandler + + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + mov x1, METHODDESC_REGISTER // pMethodDesc + + bl C_FUNC(ExecuteInterpretedMethod) + + EPILOG_WITH_TRANSITION_BLOCK_RETURN + +NESTED_END InterpreterStub, _TEXT +#endif // FEATURE_INTERPRETER diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index e240919a7395f0..a08bb3f8caf22f 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -21,6 +21,9 @@ #endif IMPORT HijackHandler IMPORT ThrowControlForThread +#ifdef FEATURE_INTERPRETER + IMPORT ExecuteInterpretedMethod +#endif #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP IMPORT g_sw_ww_table @@ -1193,6 +1196,20 @@ JIT_PollGCRarePath br x9 LEAF_END +#ifdef FEATURE_INTERPRETER + NESTED_ENTRY InterpreterStub + + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock + mov x1, METHODDESC_REGISTER ; pMethodDesc + + bl ExecuteInterpretedMethod + + EPILOG_WITH_TRANSITION_BLOCK_RETURN + + NESTED_END +#endif // FEATURE_INTERPRETER ; Must be at very end of file END diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 3354a7ec0f2ab4..d136b2465157b4 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -6611,7 +6611,11 @@ void CEEInfo::setMethodAttribs ( ftn->SetNotInline(true); } - if (attribs & (CORINFO_FLG_SWITCHED_TO_OPTIMIZED | CORINFO_FLG_SWITCHED_TO_MIN_OPT)) + if (attribs & (CORINFO_FLG_SWITCHED_TO_OPTIMIZED | CORINFO_FLG_SWITCHED_TO_MIN_OPT +#ifdef FEATURE_INTERPRETER + | CORINFO_FLG_INTERPRETER +#endif // FEATURE_INTERPRETER + )) { PrepareCodeConfig *config = GetThread()->GetCurrentPrepareCodeConfig(); if (config != nullptr) @@ -6621,6 +6625,12 @@ void CEEInfo::setMethodAttribs ( _ASSERTE(!ftn->IsJitOptimizationDisabled()); config->SetJitSwitchedToMinOpt(); } +#ifdef FEATURE_INTERPRETER + else if (attribs & CORINFO_FLG_INTERPRETER) + { + config->SetIsInterpreterCode(); + } +#endif // FEATURE_INTERPRETER #ifdef FEATURE_TIERED_COMPILATION else if (attribs & CORINFO_FLG_SWITCHED_TO_OPTIMIZED) { diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 5d541b84fbb493..eab8ae8f3232e1 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -2060,6 +2060,20 @@ class PrepareCodeConfig m_jitSwitchedToMinOpt = true; } +#ifdef FEATURE_INTERPRETER + void SetIsInterpreterCode() + { + LIMITED_METHOD_CONTRACT; + m_isInterpreterCode = true; + } + + bool IsInterpreterCode() const + { + LIMITED_METHOD_CONTRACT; + return m_isInterpreterCode; + } +#endif // FEATURE_INTERPRETER + #ifdef FEATURE_TIERED_COMPILATION public: bool JitSwitchedToOptimized() const @@ -2128,6 +2142,9 @@ class PrepareCodeConfig #ifdef FEATURE_TIERED_COMPILATION bool m_jitSwitchedToOptimized; // when a different tier was requested #endif +#ifdef FEATURE_INTERPRETER + bool m_isInterpreterCode; // The generated code is interpreter IR +#endif // FEATURE_INTERPRETER PrepareCodeConfig *m_nextInSameThread; }; diff --git a/src/coreclr/vm/precode.cpp b/src/coreclr/vm/precode.cpp index e793425d2bec50..08d4c164585e46 100644 --- a/src/coreclr/vm/precode.cpp +++ b/src/coreclr/vm/precode.cpp @@ -184,6 +184,26 @@ PCODE Precode::TryToSkipFixupPrecode(PCODE addr) #ifndef DACCESS_COMPILE +#ifdef FEATURE_INTERPRETER +InterpreterPrecode* Precode::AllocateInterpreterPrecode(PCODE byteCode, + LoaderAllocator * pLoaderAllocator, + AllocMemTracker * pamTracker) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + SIZE_T size = sizeof(InterpreterPrecode); + InterpreterPrecode* pPrecode = (InterpreterPrecode*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocAlignedMem(size, 1)); + pPrecode->Init(pPrecode, byteCode); + return pPrecode; +} +#endif // FEATURE_INTERPRETER + Precode* Precode::Allocate(PrecodeType t, MethodDesc* pMD, LoaderAllocator * pLoaderAllocator, AllocMemTracker * pamTracker) @@ -483,6 +503,18 @@ BOOL StubPrecode::IsStubPrecodeByASM(PCODE addr) #endif // TARGET_X86 } +#ifdef FEATURE_INTERPRETER +void InterpreterPrecode::Init(InterpreterPrecode* pPrecodeRX, TADDR byteCodeAddr) +{ + WRAPPER_NO_CONTRACT; + InterpreterPrecodeData *pStubData = GetData(); + + pStubData->Target = (PCODE)InterpreterStub; + pStubData->ByteCodeAddr = byteCodeAddr; + pStubData->Type = InterpreterPrecode::Type; +} +#endif // FEATURE_INTERPRETER + #ifdef HAS_NDIRECT_IMPORT_PRECODE void NDirectImportPrecode::Init(NDirectImportPrecode* pPrecodeRX, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) diff --git a/src/coreclr/vm/precode.h b/src/coreclr/vm/precode.h index 894a708e195f6b..ebe53d16463d60 100644 --- a/src/coreclr/vm/precode.h +++ b/src/coreclr/vm/precode.h @@ -88,6 +88,10 @@ extern "C" void StubPrecodeCode(); extern "C" void StubPrecodeCode_End(); #endif +#ifdef FEATURE_INTERPRETER +extern "C" void InterpreterStub(); +#endif + // Regular precode struct StubPrecode { @@ -204,6 +208,37 @@ typedef DPTR(NDirectImportPrecode) PTR_NDirectImportPrecode; #endif // HAS_NDIRECT_IMPORT_PRECODE +#ifdef FEATURE_INTERPRETER +struct InterpreterPrecodeData +{ + TADDR ByteCodeAddr; + PCODE Target; + BYTE Type; +}; + +typedef DPTR(InterpreterPrecodeData) PTR_InterpreterPrecodeData; + +struct InterpreterPrecode +{ + static const int Type = 0x06; + + BYTE m_code[StubPrecode::CodeSize]; + + void Init(InterpreterPrecode* pPrecodeRX, TADDR byteCodeAddr); + + PTR_InterpreterPrecodeData GetData() const + { + LIMITED_METHOD_CONTRACT; + return dac_cast(dac_cast(this) + GetStubCodePageSize()); + } + + PCODE GetEntryPoint() + { + LIMITED_METHOD_CONTRACT; + return PINSTRToPCODE(dac_cast(this)); + } +}; +#endif // FEATURE_INTERPRETER #ifdef HAS_FIXUP_PRECODE @@ -347,6 +382,9 @@ typedef DPTR(class Precode) PTR_Precode; enum PrecodeType { PRECODE_INVALID = InvalidPrecode::Type, PRECODE_STUB = StubPrecode::Type, +#ifdef FEATURE_INTERPRETER + PRECODE_INTERPRETER = InterpreterPrecode::Type, +#endif // FEATURE_INTERPRETER #ifdef HAS_NDIRECT_IMPORT_PRECODE PRECODE_NDIRECT_IMPORT = NDirectImportPrecode::Type, #endif // HAS_NDIRECT_IMPORT_PRECODE @@ -534,6 +572,10 @@ class Precode { static Precode* Allocate(PrecodeType t, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator, AllocMemTracker *pamTracker); +#ifdef FEATURE_INTERPRETER + static InterpreterPrecode* AllocateInterpreterPrecode(PCODE byteCode, + LoaderAllocator * pLoaderAllocator, AllocMemTracker * pamTracker); +#endif // FEATURE_INTERPRETER void Init(Precode* pPrecodeRX, PrecodeType t, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator); #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index b78092f7156336..9e2c581413ed2a 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -426,6 +426,16 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) LOG((LF_CLASSLOADER, LL_INFO1000000, " In PrepareILBasedCode, calling JitCompileCode\n")); pCode = JitCompileCode(pConfig); +#ifdef FEATURE_INTERPRETER + if (pConfig->IsInterpreterCode()) + { + AllocMemTracker amt; + InterpreterPrecode* pPrecode = Precode::AllocateInterpreterPrecode(pCode, GetLoaderAllocator(), &amt); + amt.SuppressRelease(); + pCode = PINSTRToPCODE(pPrecode->GetEntryPoint()); + SetNativeCodeInterlocked(pCode); + } +#endif // FEATURE_INTERPRETER } else { @@ -1829,6 +1839,9 @@ PrepareCodeConfig::PrepareCodeConfig(NativeCodeVersion codeVersion, BOOL needsMu m_jitSwitchedToMinOpt(false), #ifdef FEATURE_TIERED_COMPILATION m_jitSwitchedToOptimized(false), +#endif +#ifdef FEATURE_INTERPRETER + m_isInterpreterCode(false), #endif m_nextInSameThread(nullptr) {} @@ -2683,6 +2696,20 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method return pbRetVal; } +#ifdef FEATURE_INTERPRETER +extern "C" void STDCALL ExecuteInterpretedMethod(TransitionBlock* pTransitionBlock, TADDR byteCodeAddr) +{ + CodeHeader* pCodeHeader = EEJitManager::GetCodeHeaderFromStartAddress(byteCodeAddr); + + EEJitManager *pManager = ExecutionManager::GetEEJitManager(); + MethodDesc *pMD = pCodeHeader->GetMethodDesc(); + + // TODO-Interp: call the interpreter method execution entry point + // Argument registers are in the TransitionBlock + // The stack arguments are right after the pTransitionBlock +} +#endif // FEATURE_INTERPRETER + #ifdef _DEBUG // // These are two functions for testing purposes only, in debug builds only. They can be used by setting