Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2013-03-24 05:43:27 +0400
committerZoltan Varga <vargaz@gmail.com>2013-03-24 05:43:27 +0400
commit70141dc9f523282bc3b3b947cc3e36ef594ad15e (patch)
tree50434ccc4e2b2c97ebb7ba52f91d04cdee8a1a84 /mcs
parent605e4d6313259e649542e1ba8aff8326027d9b36 (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.cs202
-rw-r--r--mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs66
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 ()
{