Permalink
Browse files

Implement the Marshal.Read/WriteXXX methods using unsafe code instead…

… of icalls.
  • Loading branch information...
1 parent 605e4d6 commit 70141dc9f523282bc3b3b947cc3e36ef594ad15e @vargaz vargaz committed Mar 24, 2013
@@ -705,11 +705,16 @@ public static int QueryInterface (IntPtr pUnk, ref Guid iid, out IntPtr ppv)
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 @@ public static byte ReadByte ([In, MarshalAs (UnmanagedType.AsAny)] object ptr, i
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 @@ public static short ReadInt16 ([In, MarshalAs(UnmanagedType.AsAny)] object ptr,
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 @@ public static int ReadInt32 ([In, MarshalAs(UnmanagedType.AsAny)] object ptr, in
[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 @@ public static IntPtr ReadIntPtr (IntPtr ptr)
}
[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 @@ public static IntPtr SecureStringToGlobalAllocUnicode (SecureString s)
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 @@ public static void WriteByte ([In, Out, MarshalAs (UnmanagedType.AsAny)] object
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 @@ public static void WriteInt16 ([In, Out, MarshalAs (UnmanagedType.AsAny)] object
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 @@ public static void WriteInt16([In, Out] object ptr, int ofs, char val)
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 @@ public static void WriteInt32([In, Out, MarshalAs(UnmanagedType.AsAny)] object p
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 @@ public static void WriteIntPtr (IntPtr ptr, IntPtr val)
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)
@@ -259,6 +259,57 @@ public void StringToHGlobalUni ()
}
[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 @@ public void ReadInt32_Endian ()
}
[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 ()
{
Oops, something went wrong.

0 comments on commit 70141dc

Please sign in to comment.