diff options
author | Zoltan Varga <vargaz@gmail.com> | 2013-03-24 05:43:27 +0400 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2013-03-24 05:43:27 +0400 |
commit | 70141dc9f523282bc3b3b947cc3e36ef594ad15e (patch) | |
tree | 50434ccc4e2b2c97ebb7ba52f91d04cdee8a1a84 /mcs | |
parent | 605e4d6313259e649542e1ba8aff8326027d9b36 (diff) |
Implement the Marshal.Read/WriteXXX methods using unsafe code instead of icalls.
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs | 202 | ||||
-rw-r--r-- | mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs | 66 |
2 files changed, 235 insertions, 33 deletions
diff --git a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs index 746e1f6f35f..863dcf3b0fb 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs @@ -705,11 +705,16 @@ namespace System.Runtime.InteropServices public static byte ReadByte (IntPtr ptr) { - return ReadByte (ptr, 0); + unsafe { + return *(byte*)ptr; + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static byte ReadByte (IntPtr ptr, int ofs); + public static byte ReadByte (IntPtr ptr, int ofs) { + unsafe { + return *(byte*)(ptr + ofs); + } + } [MonoTODO] [SuppressUnmanagedCodeSecurity] @@ -720,11 +725,34 @@ namespace System.Runtime.InteropServices public static short ReadInt16 (IntPtr ptr) { - return ReadInt16 (ptr, 0); + // The mono JIT can't inline this due to the hight number of calls + // return ReadInt16 (ptr, 0); + if (ptr.ToInt32 () % 2 == 0) { + unsafe { + return *(short*)ptr; + } + } else { + unsafe { + short s; + String.memcpy ((byte*)&s, (byte*)ptr, 2); + return s; + } + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static short ReadInt16 (IntPtr ptr, int ofs); + public static short ReadInt16 (IntPtr ptr, int ofs) { + if ((ptr + ofs).ToInt32 () % 2 == 0) { + unsafe { + return *(short*)(ptr + ofs); + } + } else { + unsafe { + short s; + String.memcpy ((byte*)&s, (byte*)(ptr + ofs), 2); + return s; + } + } + } [MonoTODO] [SuppressUnmanagedCodeSecurity] @@ -733,15 +761,35 @@ namespace System.Runtime.InteropServices throw new NotImplementedException (); } - [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] public static int ReadInt32 (IntPtr ptr) { - return ReadInt32 (ptr, 0); + if (ptr.ToInt32 () % 4 == 0) { + unsafe { + return *(int*)ptr; + } + } else { + unsafe { + int s; + String.memcpy ((byte*)&s, (byte*)ptr, 4); + return s; + } + } } [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static int ReadInt32 (IntPtr ptr, int ofs); + public static int ReadInt32 (IntPtr ptr, int ofs) { + if ((ptr + ofs).ToInt32 () % 4 == 0) { + unsafe { + return *(int*)(ptr + ofs); + } + } else { + unsafe { + int s; + String.memcpy ((byte*)&s, (byte*)(ptr + ofs), 4); + return s; + } + } + } [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] [MonoTODO] @@ -754,11 +802,34 @@ namespace System.Runtime.InteropServices [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] public static long ReadInt64 (IntPtr ptr) { - return ReadInt64 (ptr, 0); + // The real alignment might be 4 on some platforms, but this is just an optimization, + // so it doesn't matter. + if (ptr.ToInt32 () % 8 == 0) { + unsafe { + return *(long*)ptr; + } + } else { + unsafe { + long s; + String.memcpy ((byte*)&s, (byte*)ptr, 8); + return s; + } + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static long ReadInt64 (IntPtr ptr, int ofs); + public static long ReadInt64 (IntPtr ptr, int ofs) { + if ((ptr + ofs).ToInt32 () % 8 == 0) { + unsafe { + return *(long*)(ptr + ofs); + } + } else { + unsafe { + long s; + String.memcpy ((byte*)&s, (byte*)(ptr + ofs), 8); + return s; + } + } + } [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] [MonoTODO] @@ -775,8 +846,12 @@ namespace System.Runtime.InteropServices } [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static IntPtr ReadIntPtr (IntPtr ptr, int ofs); + public static IntPtr ReadIntPtr (IntPtr ptr, int ofs) { + if (IntPtr.Size == 4) + return (IntPtr)ReadInt32 (ptr, ofs); + else + return (IntPtr)ReadInt64 (ptr, ofs); + } [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] [MonoTODO] @@ -1009,11 +1084,16 @@ namespace System.Runtime.InteropServices public static void WriteByte (IntPtr ptr, byte val) { - WriteByte (ptr, 0, val); + unsafe { + *(byte*)ptr = val; + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static void WriteByte (IntPtr ptr, int ofs, byte val); + public static void WriteByte (IntPtr ptr, int ofs, byte val) { + unsafe { + *(byte*)(ptr + ofs) = val; + } + } [MonoTODO] [SuppressUnmanagedCodeSecurity] @@ -1024,11 +1104,28 @@ namespace System.Runtime.InteropServices public static void WriteInt16 (IntPtr ptr, short val) { - WriteInt16 (ptr, 0, val); + if (ptr.ToInt32 () % 2 == 0) { + unsafe { + *(short*)ptr = val; + } + } else { + unsafe { + String.memcpy ((byte*)ptr, (byte*)&val, 2); + } + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static void WriteInt16 (IntPtr ptr, int ofs, short val); + public static void WriteInt16 (IntPtr ptr, int ofs, short val) { + if ((ptr + ofs).ToInt32 () % 2 == 0) { + unsafe { + *(short*)(ptr + ofs) = val; + } + } else { + unsafe { + String.memcpy ((byte*)(ptr + ofs), (byte*)&val, 2); + } + } + } [MonoTODO] [SuppressUnmanagedCodeSecurity] @@ -1039,12 +1136,12 @@ namespace System.Runtime.InteropServices public static void WriteInt16 (IntPtr ptr, char val) { - WriteInt16 (ptr, 0, val); + WriteInt16 (ptr, 0, (short)val); } - [MonoTODO] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static void WriteInt16 (IntPtr ptr, int ofs, char val); + public static void WriteInt16 (IntPtr ptr, int ofs, char val) { + WriteInt16 (ptr, ofs, (short)val); + } [MonoTODO] public static void WriteInt16([In, Out] object ptr, int ofs, char val) @@ -1054,11 +1151,28 @@ namespace System.Runtime.InteropServices public static void WriteInt32 (IntPtr ptr, int val) { - WriteInt32 (ptr, 0, val); + if (ptr.ToInt32 () % 4 == 0) { + unsafe { + *(int*)ptr = val; + } + } else { + unsafe { + String.memcpy ((byte*)ptr, (byte*)&val, 4); + } + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static void WriteInt32 (IntPtr ptr, int ofs, int val); + public static void WriteInt32 (IntPtr ptr, int ofs, int val) { + if ((ptr + ofs).ToInt32 () % 4 == 0) { + unsafe { + *(int*)(ptr + ofs) = val; + } + } else { + unsafe { + String.memcpy ((byte*)(ptr + ofs), (byte*)&val, 4); + } + } + } [MonoTODO] [SuppressUnmanagedCodeSecurity] @@ -1069,11 +1183,29 @@ namespace System.Runtime.InteropServices public static void WriteInt64 (IntPtr ptr, long val) { - WriteInt64 (ptr, 0, val); + // See ReadInt64 () + if (ptr.ToInt32 () % 8 == 0) { + unsafe { + *(long*)ptr = val; + } + } else { + unsafe { + String.memcpy ((byte*)ptr, (byte*)&val, 8); + } + } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static void WriteInt64 (IntPtr ptr, int ofs, long val); + public static void WriteInt64 (IntPtr ptr, int ofs, long val) { + if ((ptr + ofs).ToInt32 () % 8 == 0) { + unsafe { + *(long*)(ptr + ofs) = val; + } + } else { + unsafe { + String.memcpy ((byte*)(ptr + ofs), (byte*)&val, 8); + } + } + } [MonoTODO] [SuppressUnmanagedCodeSecurity] @@ -1087,8 +1219,12 @@ namespace System.Runtime.InteropServices WriteIntPtr (ptr, 0, val); } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern static void WriteIntPtr (IntPtr ptr, int ofs, IntPtr val); + public static void WriteIntPtr (IntPtr ptr, int ofs, IntPtr val) { + if (IntPtr.Size == 4) + WriteInt32 (ptr, ofs, (int)val); + else + WriteInt64 (ptr, ofs, (long)val); + } [MonoTODO] public static void WriteIntPtr([In, Out, MarshalAs(UnmanagedType.AsAny)] object ptr, int ofs, IntPtr val) diff --git a/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs b/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs index bb401e4c6d8..8731bde74ea 100644 --- a/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs @@ -259,6 +259,57 @@ namespace MonoTests.System.Runtime.InteropServices } [Test] + public void ReadIntByte () + { + IntPtr ptr = Marshal.AllocHGlobal (4); + try { + Marshal.WriteByte (ptr, 0, 0x1); + Marshal.WriteByte (ptr, 1, 0x2); + Assert.AreEqual (0x1, Marshal.ReadByte (ptr)); + Assert.AreEqual (0x1, Marshal.ReadByte (ptr, 0)); + Assert.AreEqual (0x2, Marshal.ReadByte (ptr, 1)); + } finally { + Marshal.FreeHGlobal (ptr); + } + } + + [Test] + public void ReadInt16 () + { + IntPtr ptr = Marshal.AllocHGlobal (64); + try { + Marshal.WriteInt16 (ptr, 0, 0x1234); + Marshal.WriteInt16 (ptr, 2, 0x4567); + Marshal.WriteInt16 (ptr, 5, 0x4567); + Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr)); + Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr, 0)); + Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 2)); + Assert.AreEqual (0x4567, Marshal.ReadInt16 ((ptr + 5))); + Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 5)); + } finally { + Marshal.FreeHGlobal (ptr); + } + } + + [Test] + public void ReadInt32 () + { + IntPtr ptr = Marshal.AllocHGlobal (64); + try { + Marshal.WriteInt32 (ptr, 0, 0x12345678); + Marshal.WriteInt32 (ptr, 4, 0x77654321); + Marshal.WriteInt32 (ptr, 10, 0x77654321); + Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr)); + Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr, 0)); + Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 4)); + Assert.AreEqual (0x77654321, Marshal.ReadInt32 ((ptr + 10))); + Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 10)); + } finally { + Marshal.FreeHGlobal (ptr); + } + } + + [Test] public void ReadInt32_Endian () { IntPtr ptr = Marshal.AllocHGlobal (4); @@ -279,6 +330,21 @@ namespace MonoTests.System.Runtime.InteropServices } [Test] + public void ReadInt64 () + { + IntPtr ptr = Marshal.AllocHGlobal (16); + try { + Marshal.WriteInt64 (ptr, 0, 0x12345678ABCDEFL); + Marshal.WriteInt64 (ptr, 8, 0x87654321ABCDEFL); + Assert.AreEqual (0x12345678ABCDEFL, Marshal.ReadInt64 (ptr)); + Assert.AreEqual (0x12345678ABCDEFL, Marshal.ReadInt64 (ptr, 0)); + Assert.AreEqual (0x87654321ABCDEFL, Marshal.ReadInt64 (ptr, 8)); + } finally { + Marshal.FreeHGlobal (ptr); + } + } + + [Test] [Category ("MobileNotWorking")] public void BSTR_Roundtrip () { |