diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index b17c13aea805b9..13a93f9340b62e 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -1178,6 +1178,18 @@ HaveInterpThreadContext EPILOG_RETURN NESTED_END InterpreterStubRetBuff + NESTED_ENTRY InterpreterStubRetBuffX1 + PROLOG_SAVE_REG_PAIR fp, lr, #-16! + ; The +16 is for the fp, lr above + add x0, sp, #__PWTB_TransitionBlock + 16 + ; Load the return buffer address from incoming x1 before clobbering x1 + mov x2, x1 + mov x1, x19 ; the IR bytecode pointer + bl ExecuteInterpretedMethod + EPILOG_RESTORE_REG_PAIR fp, lr, #16! + EPILOG_RETURN + NESTED_END InterpreterStubRetBuffX1 + NESTED_ENTRY InterpreterStubRet2I8 PROLOG_SAVE_REG_PAIR fp, lr, #-16! ; The +16 is for the fp, lr above @@ -2601,6 +2613,27 @@ CopyLoop EPILOG_RETURN NESTED_END CallJittedMethodRetBuff + ; X0 - routines array + ; X1 - interpreter stack args location + ; X2 - interpreter stack return value location + ; X3 - stack arguments size (properly aligned) + ; X4 - address of continuation return value + NESTED_ENTRY CallJittedMethodRetBuffX1 + PROLOG_SAVE_REG_PAIR fp, lr, #-32! + str x4, [fp, #16] + sub sp, sp, x3 + mov x10, x0 + mov x9, x1 + mov x1, x2 + ldr x11, [x10], #8 + blr x11 + ldr x4, [fp, #16] + str x2, [x4] + EPILOG_STACK_RESTORE + EPILOG_RESTORE_REG_PAIR fp, lr, #32! + EPILOG_RETURN + NESTED_END CallJittedMethodRetBuffX1 + ; X0 - routines array ; X1 - interpreter stack args location ; X2 - interpreter stack return value location diff --git a/src/coreclr/vm/callingconvention.h b/src/coreclr/vm/callingconvention.h index 2100e180403f0c..2a609a7ad4e604 100644 --- a/src/coreclr/vm/callingconvention.h +++ b/src/coreclr/vm/callingconvention.h @@ -1091,7 +1091,15 @@ int ArgIteratorTemplate::GetRetBuffArgOffset() // x86 is special as always ret += this->HasThis() ? offsetof(ArgumentRegisters, EDX) : offsetof(ArgumentRegisters, ECX); #elif TARGET_ARM64 - ret = TransitionBlock::GetOffsetOfRetBuffArgReg(); + if (this->IsRetBuffPassedAsFirstArg()) + { + if (this->HasThis()) + ret += TARGET_REGISTER_SIZE; + } + else + { + ret = TransitionBlock::GetOffsetOfRetBuffArgReg(); + } #else if (this->HasThis()) ret += TARGET_REGISTER_SIZE; @@ -1119,7 +1127,7 @@ int ArgIteratorTemplate::GetVASigCookieOffset() ret += TARGET_REGISTER_SIZE; } - if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) + if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg()) { ret += TARGET_REGISTER_SIZE; } @@ -1172,7 +1180,7 @@ int ArgIteratorTemplate::GetParamTypeArgOffset() ret += TARGET_REGISTER_SIZE; } - if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) + if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg()) { ret += TARGET_REGISTER_SIZE; } @@ -1229,7 +1237,7 @@ int ArgIteratorTemplate::GetAsyncContinuationArgOffset() ret += TARGET_REGISTER_SIZE; } - if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) + if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg()) { ret += TARGET_REGISTER_SIZE; } @@ -1265,7 +1273,7 @@ int ArgIteratorTemplate::GetNextOffset() if (this->HasThis()) numRegistersUsed++; - if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) + if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg()) numRegistersUsed++; _ASSERTE(!this->IsVarArg() || !this->HasParamType()); @@ -2070,7 +2078,7 @@ void ArgIteratorTemplate::ForceSigWalk() if (this->HasThis()) numRegistersUsed++; - if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) + if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg()) numRegistersUsed++; if (this->IsVarArg()) @@ -2267,6 +2275,11 @@ class ArgIteratorBase #endif // defined(UNIX_AMD64_ABI) public: + FORCEINLINE BOOL IsRetBuffPassedAsFirstArg() + { + return ::IsRetBuffPassedAsFirstArg(); + } + BOOL HasThis() { LIMITED_METHOD_CONTRACT; @@ -2361,6 +2374,26 @@ class PInvokeArgIterator : public ArgIteratorTemplate } }; +#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS) +class ArgIteratorBaseForWindowsArm64PInvokeThisCall : public ArgIteratorBaseForPInvoke +{ +public: + FORCEINLINE BOOL IsRetBuffPassedAsFirstArg() + { + return TRUE; + } +}; + +class WindowsArm64PInvokeThisCallArgIterator : public ArgIteratorTemplate +{ +public: + WindowsArm64PInvokeThisCallArgIterator(MetaSig* pSig) + { + m_pSig = pSig; + } +}; +#endif // defined(TARGET_ARM64) && defined(TARGET_WINDOWS) + // Conventience helper inline BOOL HasRetBuffArg(MetaSig * pSig) { diff --git a/src/coreclr/vm/callstubgenerator.cpp b/src/coreclr/vm/callstubgenerator.cpp index cf172b3108fbfc..169906f1fb5316 100644 --- a/src/coreclr/vm/callstubgenerator.cpp +++ b/src/coreclr/vm/callstubgenerator.cpp @@ -2148,6 +2148,10 @@ extern "C" void CallJittedMethodRetBuffR1(PCODE *routines, int8_t*pArgs, int8_t* extern "C" void InterpreterStubRetBuffR0(); extern "C" void InterpreterStubRetBuffR1(); #else // !TARGET_AMD64 && !TARGET_ARM +#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS) +extern "C" void CallJittedMethodRetBuffX1(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation); +extern "C" void InterpreterStubRetBuffX1(); +#endif extern "C" void CallJittedMethodRetBuff(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation); extern "C" void InterpreterStubRetBuff(); #endif // TARGET_AMD64 @@ -2256,12 +2260,17 @@ CallStubHeader::InvokeFunctionPtr CallStubGenerator::GetInvokeFunctionPtr(CallSt case ReturnTypeBuffArg2: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffRSI); #endif // TARGET_WINDOWS +#elif defined(TARGET_ARM64) && defined(TARGET_WINDOWS) + case ReturnTypeBuffArg2: + INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffX1); + case ReturnTypeBuff: + INVOKE_FUNCTION_PTR(CallJittedMethodRetBuff); #elif defined(TARGET_ARM) case ReturnTypeBuffArg1: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffR0); case ReturnTypeBuffArg2: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffR1); -#else // !TARGET_AMD64 && !TARGET_ARM +#else // !TARGET_AMD64 && !TARGET_ARM && !(TARGET_ARM64 && TARGET_WINDOWS) case ReturnTypeBuff: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuff); #endif // TARGET_AMD64 @@ -2370,12 +2379,17 @@ PCODE CallStubGenerator::GetInterpreterReturnTypeHandler(CallStubGenerator::Retu #else RETURN_TYPE_HANDLER(InterpreterStubRetBuffRSI); #endif +#elif defined(TARGET_ARM64) && defined(TARGET_WINDOWS) + case ReturnTypeBuffArg2: + RETURN_TYPE_HANDLER(InterpreterStubRetBuffX1); + case ReturnTypeBuff: + RETURN_TYPE_HANDLER(InterpreterStubRetBuff); #elif defined(TARGET_ARM) case ReturnTypeBuffArg1: RETURN_TYPE_HANDLER(InterpreterStubRetBuffR0); case ReturnTypeBuffArg2: RETURN_TYPE_HANDLER(InterpreterStubRetBuffR1); -#else // !TARGET_AMD64 && !TARGET_ARM +#else // !TARGET_AMD64 && !TARGET_ARM && !(TARGET_ARM64 && TARGET_WINDOWS) case ReturnTypeBuff: RETURN_TYPE_HANDLER(InterpreterStubRetBuff); #endif // TARGET_AMD64 @@ -2747,7 +2761,16 @@ void CallStubGenerator::ComputeCallStub(MetaSig &sig, PCODE *pRoutines, MethodDe if (hasUnmanagedCallConv) { - ComputeCallStubWorker(hasUnmanagedCallConv, unmanagedCallConv, sig, pRoutines, pMD); +#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS) + if (callConvIsInstanceMethodCallConv(unmanagedCallConv)) + { + ComputeCallStubWorker(hasUnmanagedCallConv, unmanagedCallConv, sig, pRoutines, pMD); + } + else +#endif // defined(TARGET_ARM64) && defined(TARGET_WINDOWS) + { + ComputeCallStubWorker(hasUnmanagedCallConv, unmanagedCallConv, sig, pRoutines, pMD); + } } else { @@ -2763,17 +2786,7 @@ void CallStubGenerator::ComputeCallStubWorker(bool hasUnmanagedCallConv, CorInfo if (hasUnmanagedCallConv) { - switch (unmanagedCallConv) - { - case CorInfoCallConvExtension::Thiscall: - case CorInfoCallConvExtension::CMemberFunction: - case CorInfoCallConvExtension::StdcallMemberFunction: - case CorInfoCallConvExtension::FastcallMemberFunction: - unmanagedThisCallConv = true; - break; - default: - break; - } + unmanagedThisCallConv = callConvIsInstanceMethodCallConv(unmanagedCallConv); } #if defined(TARGET_WINDOWS) @@ -3301,6 +3314,13 @@ CallStubGenerator::ReturnType CallStubGenerator::GetReturnType(ArgIteratorType * return ReturnTypeBuffArg1; } #else +#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64) + if (pArgIt->IsRetBuffPassedAsFirstArg()) + { + _ASSERTE(pArgIt->HasThis()); + return ReturnTypeBuffArg2; + } +#endif return ReturnTypeBuff; #endif // TARGET_AMD64 } diff --git a/src/coreclr/vm/callstubgenerator.h b/src/coreclr/vm/callstubgenerator.h index 0835d4b5de5d21..818645a8b6123a 100644 --- a/src/coreclr/vm/callstubgenerator.h +++ b/src/coreclr/vm/callstubgenerator.h @@ -83,6 +83,9 @@ class CallStubGenerator ReturnTypeBuffArg1, ReturnTypeBuffArg2, #else +#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS) + ReturnTypeBuffArg2, +#endif ReturnTypeBuff, #endif #ifdef UNIX_AMD64_ABI diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 736954fac9f78e..461dbf1a4a1d01 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -238,6 +238,11 @@ class ArgIteratorBaseForMethodInvoke #endif // defined(UNIX_AMD64_ABI) public: + FORCEINLINE BOOL IsRetBuffPassedAsFirstArg() + { + return ::IsRetBuffPassedAsFirstArg(); + } + BOOL HasThis() { LIMITED_METHOD_CONTRACT;