Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/coreclr/vm/arm64/asmhelpers.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
45 changes: 39 additions & 6 deletions src/coreclr/vm/callingconvention.h
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,15 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::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;
Expand Down Expand Up @@ -1119,7 +1127,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetVASigCookieOffset()
ret += TARGET_REGISTER_SIZE;
}

if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg())
{
ret += TARGET_REGISTER_SIZE;
}
Expand Down Expand Up @@ -1172,7 +1180,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetParamTypeArgOffset()
ret += TARGET_REGISTER_SIZE;
}

if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg())
{
ret += TARGET_REGISTER_SIZE;
}
Expand Down Expand Up @@ -1229,7 +1237,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetAsyncContinuationArgOffset()
ret += TARGET_REGISTER_SIZE;
}

if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg())
{
ret += TARGET_REGISTER_SIZE;
}
Expand Down Expand Up @@ -1265,7 +1273,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
if (this->HasThis())
numRegistersUsed++;

if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg())
numRegistersUsed++;

_ASSERTE(!this->IsVarArg() || !this->HasParamType());
Expand Down Expand Up @@ -2070,7 +2078,7 @@ void ArgIteratorTemplate<ARGITERATOR_BASE>::ForceSigWalk()
if (this->HasThis())
numRegistersUsed++;

if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
if (this->HasRetBuffArg() && this->IsRetBuffPassedAsFirstArg())
numRegistersUsed++;

if (this->IsVarArg())
Expand Down Expand Up @@ -2267,6 +2275,11 @@ class ArgIteratorBase
#endif // defined(UNIX_AMD64_ABI)

public:
FORCEINLINE BOOL IsRetBuffPassedAsFirstArg()
{
return ::IsRetBuffPassedAsFirstArg();
}

BOOL HasThis()
{
LIMITED_METHOD_CONTRACT;
Expand Down Expand Up @@ -2361,6 +2374,26 @@ class PInvokeArgIterator : public ArgIteratorTemplate<ArgIteratorBaseForPInvoke>
}
};

#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS)
class ArgIteratorBaseForWindowsArm64PInvokeThisCall : public ArgIteratorBaseForPInvoke
{
public:
FORCEINLINE BOOL IsRetBuffPassedAsFirstArg()
{
return TRUE;
}
};

class WindowsArm64PInvokeThisCallArgIterator : public ArgIteratorTemplate<ArgIteratorBaseForWindowsArm64PInvokeThisCall>
{
public:
WindowsArm64PInvokeThisCallArgIterator(MetaSig* pSig)
{
m_pSig = pSig;
}
};
#endif // defined(TARGET_ARM64) && defined(TARGET_WINDOWS)

// Conventience helper
inline BOOL HasRetBuffArg(MetaSig * pSig)
{
Expand Down
48 changes: 34 additions & 14 deletions src/coreclr/vm/callstubgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2747,7 +2761,16 @@ void CallStubGenerator::ComputeCallStub(MetaSig &sig, PCODE *pRoutines, MethodDe

if (hasUnmanagedCallConv)
{
ComputeCallStubWorker<PInvokeArgIterator>(hasUnmanagedCallConv, unmanagedCallConv, sig, pRoutines, pMD);
#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS)
if (callConvIsInstanceMethodCallConv(unmanagedCallConv))
{
ComputeCallStubWorker<WindowsArm64PInvokeThisCallArgIterator>(hasUnmanagedCallConv, unmanagedCallConv, sig, pRoutines, pMD);
}
else
#endif // defined(TARGET_ARM64) && defined(TARGET_WINDOWS)
{
ComputeCallStubWorker<PInvokeArgIterator>(hasUnmanagedCallConv, unmanagedCallConv, sig, pRoutines, pMD);
}
}
else
{
Expand All @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/callstubgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class CallStubGenerator
ReturnTypeBuffArg1,
ReturnTypeBuffArg2,
#else
#if defined(TARGET_ARM64) && defined(TARGET_WINDOWS)
ReturnTypeBuffArg2,
#endif
ReturnTypeBuff,
#endif
#ifdef UNIX_AMD64_ABI
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/vm/reflectioninvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ class ArgIteratorBaseForMethodInvoke
#endif // defined(UNIX_AMD64_ABI)

public:
FORCEINLINE BOOL IsRetBuffPassedAsFirstArg()
{
return ::IsRetBuffPassedAsFirstArg();
}

BOOL HasThis()
{
LIMITED_METHOD_CONTRACT;
Expand Down
Loading