jz GenericPInvokeCalliGenILStub
;
+ ; We need to distinguish between a MethodDesc* and an unmanaged target.
+ ; The way we do this is to shift the managed target to the left by one bit and then set the
+ ; least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ ;
+ shl PINVOKE_CALLI_TARGET_REGISTER, 1
+ or PINVOKE_CALLI_TARGET_REGISTER, 1
+
+ ;
; jump to existing IL stub
;
jmp rax
jz C_FUNC(GenericPInvokeCalliGenILStub)
//
+ // We need to distinguish between a MethodDesc* and an unmanaged target.
+ // The way we do this is to shift the managed target to the left by one bit and then set the
+ // least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ //
+ shl PINVOKE_CALLI_TARGET_REGISTER, 1
+ or PINVOKE_CALLI_TARGET_REGISTER, 1
+
+ //
// jump to existing IL stub
//
jmp rax
; if null goto stub generation
cbz x9, %0
+ IF "$FuncPrefix" == "GenericPInvokeCalli"
+ ;
+ ; We need to distinguish between a MethodDesc* and an unmanaged target.
+ ; The way we do this is to shift the managed target to the left by one bit and then set the
+ ; least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ ;
+ lsl x9, x9, #1
+ orr x9, x9, #1
+ ENDIF
EPILOG_BRANCH_REG x9
// $VASigCookieReg : register which contains the VASigCookie
// $SaveFPArgs : "Yes" or "No" . For varidic functions FP Args are not present in FP regs
// So need not save FP Args registers for vararg Pinvoke
-.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs
+.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs,ShiftLeftAndOrSecret=0
NESTED_ENTRY \__PInvokeStubFuncName, _TEXT, NoHandler
// if null goto stub generation
cbz x9, LOCAL_LABEL(\__PInvokeStubFuncName\()_0)
+ .if (\ShiftLeftAndOrSecret == 1)
+ //
+ // We need to distinguish between a MethodDesc* and an unmanaged target.
+ // The way we do this is to shift the managed target to the left by one bit and then set the
+ // least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ //
+ lsl x9, x9, #1
+ orr x9, x9, #1
+ .endif
+
EPILOG_BRANCH_REG x9
LOCAL_LABEL(\__PInvokeStubFuncName\()_0):
// x15 = VASigCookie*
// x12 = Unmanaged target
//
-PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x12, 1
+PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x12, 1, 1
// ------------------------------------------------------------------
// VarargPInvokeStub_RetBuffArg & VarargPInvokeGenILStub_RetBuffArg
// for managed-to-unmanaged CALLI that requires marshaling, the target is passed
// as the secret argument to the stub by GenericPInvokeCalliHelper (asmhelpers.asm)
EmitLoadStubContext(pcsEmit, dwStubFlags);
+#ifdef _WIN64
+ // the secret arg has been shifted to left and ORed with 1 (see code:GenericPInvokeCalliHelper)
+ pcsEmit->EmitLDC(1);
+ pcsEmit->EmitSHR_UN();
+#endif
}
else
#ifdef FEATURE_COMINTEROP
WRAPPER_NO_CONTRACT;
#ifdef _WIN64
+ // See code:GenericPInvokeCalliHelper
return ((m_Datum != NULL) && !(dac_cast<TADDR>(m_Datum) & 0x1));
#else // _WIN64
return ((dac_cast<TADDR>(m_Datum) & ~0xffff) != 0);
#if defined(_WIN64)
UINT_PTR target = (UINT_PTR)orefThis->GetMethodPtrAux();
+ // See code:GenericPInvokeCalliHelper
// The lowest bit is used to distinguish between MD and target on 64-bit.
target = (target << 1) | 1;