GenericPInvokeCalli shift left then or 1 (#17734)
authorSteve MacLean <sdmaclea.qdt@qualcommdatacenter.com>
Tue, 24 Apr 2018 01:39:24 +0000 (21:39 -0400)
committerJan Kotas <jkotas@microsoft.com>
Tue, 24 Apr 2018 01:39:24 +0000 (18:39 -0700)
When _WIN64 is defined vm relies on the secret arg being
shifted left and orred with #1.

Revert part of changes from #17659 to fix dotnet/corefx#29266

Fix arm64 to match amd64

Simplify dllimport.cpp

src/vm/amd64/PInvokeStubs.asm
src/vm/amd64/pinvokestubs.S
src/vm/arm64/PInvokeStubs.asm
src/vm/arm64/pinvokestubs.S
src/vm/dllimport.cpp
src/vm/frames.h
src/vm/stubhelpers.cpp

index 7255fa2..82e33ac 100644 (file)
@@ -32,6 +32,14 @@ LEAF_ENTRY GenericPInvokeCalliHelper, _TEXT
         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
index dad668a..1952164 100644 (file)
@@ -25,6 +25,14 @@ LEAF_ENTRY GenericPInvokeCalliHelper, _TEXT
         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
index e21151e..69d8a91 100644 (file)
@@ -58,6 +58,15 @@ __PInvokeGenStubFuncName SETS "$__PInvokeGenStubFuncName":CC:"_RetBuffArg"
         ; 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 
 
index f13d2da..38f4665 100644 (file)
@@ -21,7 +21,7 @@
 // $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):
@@ -97,7 +107,7 @@ PINVOKE_STUB VarargPInvokeStub, VarargPInvokeGenILStub, VarargPInvokeStubWorker,
 // 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
index c0f7d1f..dc5ae06 100644 (file)
@@ -2256,6 +2256,11 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
                 // 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
index 66520a8..0980378 100644 (file)
@@ -2957,6 +2957,7 @@ public:
         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);
index 071c879..d43c065 100644 (file)
@@ -1166,6 +1166,7 @@ FCIMPL2(void*, StubHelpers::GetDelegateTarget, DelegateObject *pThisUNSAFE, UINT
 #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;