Move UnmanagedMemoryAccessor to shared CoreLib partition (#15137)
authorJan Kotas <jkotas@microsoft.com>
Tue, 21 Nov 2017 14:01:12 +0000 (06:01 -0800)
committerGitHub <noreply@github.com>
Tue, 21 Nov 2017 14:01:12 +0000 (06:01 -0800)
src/mscorlib/Resources/Strings.resx
src/mscorlib/System.Private.CoreLib.csproj
src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
src/mscorlib/shared/System/BitConverter.cs
src/mscorlib/shared/System/IO/UnmanagedMemoryAccessor.cs [new file with mode: 0644]
src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs [deleted file]
src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs
src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs
src/vm/ecalllist.h

index a905183..b975448 100644 (file)
   <data name="Argument_OffsetAndCapacityOutOfBounds" xml:space="preserve">
     <value>Offset and capacity were greater than the size of the view.</value>
   </data>
-  <data name="Argument_OffsetAndLengthOutOfBounds" xml:space="preserve">
-    <value>Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.</value>
-  </data>
   <data name="Argument_OffsetLocalMismatch" xml:space="preserve">
     <value>The UTC Offset of the local dateTime parameter does not match the offset argument.</value>
   </data>
index 4bae50a..e39b73e 100644 (file)
     <Compile Include="$(BclSourcesRoot)\System\IO\FileLoadException.CoreCLR.cs" />
     <Compile Include="$(BclSourcesRoot)\System\IO\FileNotFoundException.CoreCLR.cs" />
     <Compile Include="$(BclSourcesRoot)\System\IO\Stream.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\IO\UnmanagedMemoryAccessor.cs" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="$(BclSourcesRoot)\System\Security\DynamicSecurityMethodAttribute.cs" />
index 7138185..ab7dc93 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\PinnedBufferMemoryStream.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\SeekOrigin.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\StreamHelpers.CopyValidation.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\IO\UnmanagedMemoryAccessor.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\UnmanagedMemoryStream.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\UnmanagedMemoryStreamWrapper.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IObservable.cs" />
index edcdd1e..6814047 100644 (file)
@@ -36,7 +36,7 @@ namespace System
             if (destination.Length < sizeof(byte))
                 return false;
 
-            Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value ? (byte)1: (byte)0);
+            Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value ? (byte)1 : (byte)0);
             return true;
         }
 
@@ -217,7 +217,7 @@ namespace System
         }
 
         // Converts an array of bytes into a char.  
-        public static char ToChar(byte[] value, int startIndex) => unchecked((char)ReadInt16(value, startIndex));
+        public static char ToChar(byte[] value, int startIndex) => unchecked((char)ToInt16(value, startIndex));
 
         // Converts a Span into a char
         public static char ToChar(ReadOnlySpan<byte> value)
@@ -227,7 +227,8 @@ namespace System
             return Unsafe.ReadUnaligned<char>(ref value.DangerousGetPinnableReference());
         }
 
-        private static short ReadInt16(byte[] value, int startIndex)
+        // Converts an array of bytes into a short.  
+        public static short ToInt16(byte[] value, int startIndex)
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
@@ -239,44 +240,27 @@ namespace System
             return Unsafe.ReadUnaligned<short>(ref value[startIndex]);
         }
 
-        private static int ReadInt32(byte[] value, int startIndex)
+        // Converts a Span into a short
+        public static short ToInt16(ReadOnlySpan<byte> value)
         {
-            if (value == null)
-                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            if (unchecked((uint)startIndex) >= unchecked((uint)value.Length))
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
-            if (startIndex > value.Length - sizeof(int))
-                ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
-
-            return Unsafe.ReadUnaligned<int>(ref value[startIndex]);
+            if (value.Length < sizeof(short))
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+            return Unsafe.ReadUnaligned<short>(ref value.DangerousGetPinnableReference());
         }
 
-        private static long ReadInt64(byte[] value, int startIndex)
+        // Converts an array of bytes into an int.  
+        public static int ToInt32(byte[] value, int startIndex)
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
             if (unchecked((uint)startIndex) >= unchecked((uint)value.Length))
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
-            if (startIndex > value.Length - sizeof(long))
+            if (startIndex > value.Length - sizeof(int))
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
 
-            return Unsafe.ReadUnaligned<long>(ref value[startIndex]);
-        }
-
-        // Converts an array of bytes into a short.  
-        public static short ToInt16(byte[] value, int startIndex) => ReadInt16(value, startIndex);
-
-        // Converts a Span into a short
-        public static short ToInt16(ReadOnlySpan<byte> value)
-        {
-            if (value.Length < sizeof(short))
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
-            return Unsafe.ReadUnaligned<short>(ref value.DangerousGetPinnableReference());
+            return Unsafe.ReadUnaligned<int>(ref value[startIndex]);
         }
 
-        // Converts an array of bytes into an int.  
-        public static int ToInt32(byte[] value, int startIndex) => ReadInt32(value, startIndex);
-
         // Converts a Span into an int
         public static int ToInt32(ReadOnlySpan<byte> value)
         {
@@ -286,7 +270,17 @@ namespace System
         }
 
         // Converts an array of bytes into a long.  
-        public static long ToInt64(byte[] value, int startIndex) => ReadInt64(value, startIndex);
+        public static long ToInt64(byte[] value, int startIndex)
+        {
+            if (value == null)
+                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+            if (unchecked((uint)startIndex) >= unchecked((uint)value.Length))
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+            if (startIndex > value.Length - sizeof(long))
+                ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
+
+            return Unsafe.ReadUnaligned<long>(ref value[startIndex]);
+        }
 
         // Converts a Span into a long
         public static long ToInt64(ReadOnlySpan<byte> value)
@@ -299,7 +293,7 @@ namespace System
         // Converts an array of bytes into an ushort.
         // 
         [CLSCompliant(false)]
-        public static ushort ToUInt16(byte[] value, int startIndex) => unchecked((ushort)ReadInt16(value, startIndex));
+        public static ushort ToUInt16(byte[] value, int startIndex) => unchecked((ushort)ToInt16(value, startIndex));
 
         // Converts a Span into a ushort
         [CLSCompliant(false)]
@@ -313,7 +307,7 @@ namespace System
         // Converts an array of bytes into an uint.
         // 
         [CLSCompliant(false)]
-        public static uint ToUInt32(byte[] value, int startIndex) => unchecked((uint)ReadInt32(value, startIndex));
+        public static uint ToUInt32(byte[] value, int startIndex) => unchecked((uint)ToInt32(value, startIndex));
 
         // Convert a Span into a uint
         [CLSCompliant(false)]
@@ -327,7 +321,7 @@ namespace System
         // Converts an array of bytes into an unsigned long.
         // 
         [CLSCompliant(false)]
-        public static ulong ToUInt64(byte[] value, int startIndex) => unchecked((ulong)ReadInt64(value, startIndex));
+        public static ulong ToUInt64(byte[] value, int startIndex) => unchecked((ulong)ToInt64(value, startIndex));
 
         // Converts a Span into an unsigned long
         [CLSCompliant(false)]
@@ -339,11 +333,7 @@ namespace System
         }
 
         // Converts an array of bytes into a float.  
-        public static unsafe float ToSingle(byte[] value, int startIndex)
-        {
-            int val = ReadInt32(value, startIndex);
-            return *(float*)&val;
-        }
+        public static float ToSingle(byte[] value, int startIndex) => Int32BitsToSingle(ToInt32(value, startIndex));
 
         // Converts a Span into a float
         public static float ToSingle(ReadOnlySpan<byte> value)
@@ -354,11 +344,7 @@ namespace System
         }
 
         // Converts an array of bytes into a double.  
-        public static unsafe double ToDouble(byte[] value, int startIndex)
-        {
-            long val = ReadInt64(value, startIndex);
-            return *(double*)&val;
-        }
+        public static double ToDouble(byte[] value, int startIndex) => Int64BitsToDouble(ToInt64(value, startIndex));
 
         // Converts a Span into a double
         public static double ToDouble(ReadOnlySpan<byte> value)
diff --git a/src/mscorlib/shared/System/IO/UnmanagedMemoryAccessor.cs b/src/mscorlib/shared/System/IO/UnmanagedMemoryAccessor.cs
new file mode 100644 (file)
index 0000000..4899d57
--- /dev/null
@@ -0,0 +1,669 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** 
+** 
+**
+** Purpose: Provides a fast, AV free, cross-language way of 
+**          accessing unmanaged memory in a random fashion.
+**
+**
+===========================================================*/
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System.IO
+{
+    /// Perf notes: ReadXXX, WriteXXX (for basic types) acquire and release the 
+    /// SafeBuffer pointer rather than relying on generic Read(T) from SafeBuffer because
+    /// this gives better throughput; benchmarks showed about 12-15% better.
+    public class UnmanagedMemoryAccessor : IDisposable
+    {
+        private SafeBuffer _buffer;
+        private long _offset;
+        private long _capacity;
+        private FileAccess _access;
+        private bool _isOpen;
+        private bool _canRead;
+        private bool _canWrite;
+
+        protected UnmanagedMemoryAccessor()
+        {
+            _isOpen = false;
+        }
+
+        public UnmanagedMemoryAccessor(SafeBuffer buffer, long offset, long capacity)
+        {
+            Initialize(buffer, offset, capacity, FileAccess.Read);
+        }
+
+        public UnmanagedMemoryAccessor(SafeBuffer buffer, long offset, long capacity, FileAccess access)
+        {
+            Initialize(buffer, offset, capacity, access);
+        }
+
+        protected void Initialize(SafeBuffer buffer, long offset, long capacity, FileAccess access)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException(nameof(buffer));
+            }
+            if (offset < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (capacity < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (buffer.ByteLength < (ulong)(offset + capacity))
+            {
+                throw new ArgumentException(SR.Argument_OffsetAndCapacityOutOfBounds);
+            }
+            if (access < FileAccess.Read || access > FileAccess.ReadWrite)
+            {
+                throw new ArgumentOutOfRangeException(nameof(access));
+            }
+
+            if (_isOpen)
+            {
+                throw new InvalidOperationException(SR.InvalidOperation_CalledTwice);
+            }
+
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    buffer.AcquirePointer(ref pointer);
+                    if (((byte*)((long)pointer + offset + capacity)) < pointer)
+                    {
+                        throw new ArgumentException(SR.Argument_UnmanagedMemAccessorWrapAround);
+                    }
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        buffer.ReleasePointer();
+                    }
+                }
+            }
+
+            _offset = offset;
+            _buffer = buffer;
+            _capacity = capacity;
+            _access = access;
+            _isOpen = true;
+            _canRead = (_access & FileAccess.Read) != 0;
+            _canWrite = (_access & FileAccess.Write) != 0;
+        }
+
+        public long Capacity => _capacity;
+
+        public bool CanRead => _isOpen && _canRead;
+
+        public bool CanWrite => _isOpen && _canWrite;
+
+        protected virtual void Dispose(bool disposing)
+        {
+            _isOpen = false;
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected bool IsOpen => _isOpen;
+
+        // ************** Read Methods ****************/
+
+        public bool ReadBoolean(long position) => ReadByte(position) != 0;
+
+        public byte ReadByte(long position)
+        {
+            EnsureSafeToRead(position, sizeof(byte));
+
+            byte result;
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    result = *((byte*)(pointer + _offset + position));
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+            return result;
+        }
+
+        public char ReadChar(long position) => unchecked((char)ReadInt16(position));
+
+        public short ReadInt16(long position)
+        {
+            EnsureSafeToRead(position, sizeof(short));
+
+            short result;
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    result = Unsafe.ReadUnaligned<short>(pointer + _offset + position);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+            return result;
+        }
+
+        public int ReadInt32(long position)
+        {
+            EnsureSafeToRead(position, sizeof(int));
+
+            int result;
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    result = Unsafe.ReadUnaligned<int>(pointer + _offset + position);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+            return result;
+        }
+
+        public long ReadInt64(long position)
+        {
+            EnsureSafeToRead(position, sizeof(long));
+
+            long result;
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    result = Unsafe.ReadUnaligned<long>(pointer + _offset + position);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+            return result;
+        }
+
+        public decimal ReadDecimal(long position)
+        {
+            const int ScaleMask = 0x00FF0000;
+            const int SignMask = unchecked((int)0x80000000);
+
+            EnsureSafeToRead(position, sizeof(decimal));
+
+            int lo, mid, hi, flags;
+
+            unsafe
+            {
+                byte* pointer = null;
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    pointer += (_offset + position);
+
+                    lo = Unsafe.ReadUnaligned<int>(pointer);
+                    mid = Unsafe.ReadUnaligned<int>(pointer + 4);
+                    hi = Unsafe.ReadUnaligned<int>(pointer + 8);
+                    flags = Unsafe.ReadUnaligned<int>(pointer + 12);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+
+            // Check for invalid Decimal values
+            if (!((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)))
+            {
+                throw new ArgumentException(SR.Arg_BadDecimal); // Throw same Exception type as Decimal(int[]) ctor for compat
+            }
+
+            bool isNegative = (flags & SignMask) != 0;
+            byte scale = (byte)(flags >> 16);
+
+            return new decimal(lo, mid, hi, isNegative, scale);
+        }
+
+        public float ReadSingle(long position) => BitConverter.Int32BitsToSingle(ReadInt32(position));
+
+        public double ReadDouble(long position) => BitConverter.Int64BitsToDouble(ReadInt64(position));
+
+        [CLSCompliant(false)]
+        public sbyte ReadSByte(long position) => unchecked((sbyte)ReadByte(position));
+
+        [CLSCompliant(false)]
+        public ushort ReadUInt16(long position) => unchecked((ushort)ReadInt16(position));
+
+        [CLSCompliant(false)]
+        public uint ReadUInt32(long position) => unchecked((uint)ReadInt32(position));
+
+        [CLSCompliant(false)]
+        public ulong ReadUInt64(long position) => unchecked((ulong)ReadInt64(position));
+
+        // Reads a struct of type T from unmanaged memory, into the reference pointed to by ref value.  
+        // Note: this method is not safe, since it overwrites the contents of a structure, it can be 
+        // used to modify the private members of a struct.
+        // This method is most performant when used with medium to large sized structs
+        // (larger than 8 bytes -- though this is number is JIT and architecture dependent).   As 
+        // such, it is best to use the ReadXXX methods for small standard types such as ints, longs, 
+        // bools, etc.
+        public void Read<T>(long position, out T structure) where T : struct
+        {
+            if (position < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+
+            if (!_isOpen)
+            {
+                throw new ObjectDisposedException(nameof(UnmanagedMemoryAccessor), SR.ObjectDisposed_ViewAccessorClosed);
+            }
+            if (!_canRead)
+            {
+                throw new NotSupportedException(SR.NotSupported_Reading);
+            }
+
+            uint sizeOfT = SafeBuffer.SizeOf<T>();
+            if (position > _capacity - sizeOfT)
+            {
+                if (position >= _capacity)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
+                }
+                else
+                {
+                    throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToRead, typeof(T)), nameof(position));
+                }
+            }
+
+            structure = _buffer.Read<T>((ulong)(_offset + position));
+        }
+
+        // Reads 'count' structs of type T from unmanaged memory, into 'array' starting at 'offset'.  
+        // Note: this method is not safe, since it overwrites the contents of structures, it can 
+        // be used to modify the private members of a struct.
+        public int ReadArray<T>(long position, T[] array, int offset, int count) where T : struct
+        {
+            if (array == null)
+            {
+                throw new ArgumentNullException(nameof(array), SR.ArgumentNull_Buffer);
+            }
+            if (offset < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (count < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (array.Length - offset < count)
+            {
+                throw new ArgumentException(SR.Argument_InvalidOffLen);
+            }
+            if (!_isOpen)
+            {
+                throw new ObjectDisposedException(nameof(UnmanagedMemoryAccessor), SR.ObjectDisposed_ViewAccessorClosed);
+            }
+            if (!_canRead)
+            {
+                throw new NotSupportedException(SR.NotSupported_Reading);
+            }
+            if (position < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+
+            uint sizeOfT = SafeBuffer.AlignedSizeOf<T>();
+
+            // only check position and ask for fewer Ts if count is too big
+            if (position >= _capacity)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
+            }
+
+            int n = count;
+            long spaceLeft = _capacity - position;
+            if (spaceLeft < 0)
+            {
+                n = 0;
+            }
+            else
+            {
+                ulong spaceNeeded = (ulong)(sizeOfT * count);
+                if ((ulong)spaceLeft < spaceNeeded)
+                {
+                    n = (int)(spaceLeft / sizeOfT);
+                }
+            }
+
+            _buffer.ReadArray<T>((ulong)(_offset + position), array, offset, n);
+
+            return n;
+        }
+
+        // ************** Write Methods ****************/
+
+        public void Write(long position, bool value) => Write(position, (byte)(value ? 1 : 0));
+
+        public void Write(long position, byte value)
+        {
+            EnsureSafeToWrite(position, sizeof(byte));
+
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    *((byte*)(pointer + _offset + position)) = value;
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+        }
+
+        public void Write(long position, char value) => Write(position, unchecked((short)value));
+
+        public void Write(long position, short value)
+        {
+            EnsureSafeToWrite(position, sizeof(short));
+
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    Unsafe.WriteUnaligned<short>(pointer + _offset + position, value);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+        }
+
+        public void Write(long position, int value)
+        {
+            EnsureSafeToWrite(position, sizeof(int));
+
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    Unsafe.WriteUnaligned<int>(pointer + _offset + position, value);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+        }
+
+        public void Write(long position, long value)
+        {
+            EnsureSafeToWrite(position, sizeof(long));
+
+            unsafe
+            {
+                byte* pointer = null;
+
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    Unsafe.WriteUnaligned<long>(pointer + _offset + position, value);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+        }
+
+        public void Write(long position, decimal value)
+        {
+            EnsureSafeToWrite(position, sizeof(decimal));
+
+            unsafe
+            {
+                int* valuePtr = (int*)(&value);
+                int flags = *valuePtr;
+                int hi = *(valuePtr + 1);
+                int lo = *(valuePtr + 2);
+                int mid = *(valuePtr + 3);
+
+                byte* pointer = null;
+                try
+                {
+                    _buffer.AcquirePointer(ref pointer);
+                    pointer += (_offset + position);
+
+                    Unsafe.WriteUnaligned<int>(pointer, lo);
+                    Unsafe.WriteUnaligned<int>(pointer + 4, mid);
+                    Unsafe.WriteUnaligned<int>(pointer + 8, hi);
+                    Unsafe.WriteUnaligned<int>(pointer + 12, flags);
+                }
+                finally
+                {
+                    if (pointer != null)
+                    {
+                        _buffer.ReleasePointer();
+                    }
+                }
+            }
+        }
+
+        public void Write(long position, float value) => Write(position, BitConverter.SingleToInt32Bits(value));
+
+        public void Write(long position, double value) => Write(position, BitConverter.DoubleToInt64Bits(value));
+
+        [CLSCompliant(false)]
+        public void Write(long position, sbyte value) => Write(position, unchecked((byte)value));
+
+        [CLSCompliant(false)]
+        public void Write(long position, ushort value) => Write(position, unchecked((short)value));
+
+        [CLSCompliant(false)]
+        public void Write(long position, uint value) => Write(position, unchecked((int)value));
+
+        [CLSCompliant(false)]
+        public void Write(long position, ulong value) => Write(position, unchecked((long)value));
+
+        // Writes the struct pointed to by ref value into unmanaged memory.  Note that this method
+        // is most performant when used with medium to large sized structs (larger than 8 bytes 
+        // though this is number is JIT and architecture dependent).   As such, it is best to use 
+        // the WriteX methods for small standard types such as ints, longs, bools, etc.
+        public void Write<T>(long position, ref T structure) where T : struct
+        {
+            if (position < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (!_isOpen)
+            {
+                throw new ObjectDisposedException(nameof(UnmanagedMemoryAccessor), SR.ObjectDisposed_ViewAccessorClosed);
+            }
+            if (!_canWrite)
+            {
+                throw new NotSupportedException(SR.NotSupported_Writing);
+            }
+
+            uint sizeOfT = SafeBuffer.SizeOf<T>();
+            if (position > _capacity - sizeOfT)
+            {
+                if (position >= _capacity)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
+                }
+                else
+                {
+                    throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToWrite, typeof(T)), nameof(position));
+                }
+            }
+
+            _buffer.Write<T>((ulong)(_offset + position), structure);
+        }
+
+        // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory. 
+        public void WriteArray<T>(long position, T[] array, int offset, int count) where T : struct
+        {
+            if (array == null)
+            {
+                throw new ArgumentNullException(nameof(array), SR.ArgumentNull_Buffer);
+            }
+            if (offset < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (count < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (array.Length - offset < count)
+            {
+                throw new ArgumentException(SR.Argument_InvalidOffLen);
+            }
+            if (position < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (position >= Capacity)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
+            }
+
+            if (!_isOpen)
+            {
+                throw new ObjectDisposedException(nameof(UnmanagedMemoryAccessor), SR.ObjectDisposed_ViewAccessorClosed);
+            }
+            if (!_canWrite)
+            {
+                throw new NotSupportedException(SR.NotSupported_Writing);
+            }
+
+            _buffer.WriteArray<T>((ulong)(_offset + position), array, offset, count);
+        }
+
+        private void EnsureSafeToRead(long position, int sizeOfType)
+        {
+            if (!_isOpen)
+            {
+                throw new ObjectDisposedException(nameof(UnmanagedMemoryAccessor), SR.ObjectDisposed_ViewAccessorClosed);
+            }
+            if (!_canRead)
+            {
+                throw new NotSupportedException(SR.NotSupported_Reading);
+            }
+            if (position < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (position > _capacity - sizeOfType)
+            {
+                if (position >= _capacity)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
+                }
+                else
+                {
+                    throw new ArgumentException(SR.Argument_NotEnoughBytesToRead, nameof(position));
+                }
+            }
+        }
+
+        private void EnsureSafeToWrite(long position, int sizeOfType)
+        {
+            if (!_isOpen)
+            {
+                throw new ObjectDisposedException(nameof(UnmanagedMemoryAccessor), SR.ObjectDisposed_ViewAccessorClosed);
+            }
+            if (!_canWrite)
+            {
+                throw new NotSupportedException(SR.NotSupported_Writing);
+            }
+            if (position < 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
+            }
+            if (position > _capacity - sizeOfType)
+            {
+                if (position >= _capacity)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
+                }
+                else
+                {
+                    throw new ArgumentException(SR.Argument_NotEnoughBytesToWrite, nameof(position));
+                }
+            }
+        }
+    }
+}
diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs
deleted file mode 100644 (file)
index 43f2869..0000000
+++ /dev/null
@@ -1,1077 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-** 
-** 
-**
-** Purpose: Provides a fast, AV free, cross-language way of 
-**          accessing unmanaged memory in a random fashion.
-**
-**
-===========================================================*/
-
-using System;
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.Versioning;
-using Microsoft.Win32.SafeHandles;
-using System.Diagnostics;
-
-namespace System.IO
-{
-    /// Perf notes: ReadXXX, WriteXXX (for basic types) acquire and release the 
-    /// SafeBuffer pointer rather than relying on generic Read(T) from SafeBuffer because
-    /// this gives better throughput; benchmarks showed about 12-15% better.
-    public class UnmanagedMemoryAccessor : IDisposable
-    {
-        private SafeBuffer _buffer;
-        private Int64 _offset;
-        private Int64 _capacity;
-        private FileAccess _access;
-        private bool _isOpen;
-        private bool _canRead;
-        private bool _canWrite;
-
-        protected UnmanagedMemoryAccessor()
-        {
-            _isOpen = false;
-        }
-
-        #region SafeBuffer ctors and initializers
-        // <SecurityKernel Critical="True" Ring="1">
-        // <ReferencesCritical Name="Method: Initialize(SafeBuffer, Int64, Int64, FileAccess):Void" Ring="1" />
-        // </SecurityKernel>
-        public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity)
-        {
-            Initialize(buffer, offset, capacity, FileAccess.Read);
-        }
-
-        public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access)
-        {
-            Initialize(buffer, offset, capacity, access);
-        }
-
-        protected void Initialize(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access)
-        {
-            if (buffer == null)
-            {
-                throw new ArgumentNullException(nameof(buffer));
-            }
-            if (offset < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (capacity < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (buffer.ByteLength < (UInt64)(offset + capacity))
-            {
-                throw new ArgumentException(SR.Argument_OffsetAndCapacityOutOfBounds);
-            }
-            if (access < FileAccess.Read || access > FileAccess.ReadWrite)
-            {
-                throw new ArgumentOutOfRangeException(nameof(access));
-            }
-
-            if (_isOpen)
-            {
-                throw new InvalidOperationException(SR.InvalidOperation_CalledTwice);
-            }
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    buffer.AcquirePointer(ref pointer);
-                    if (((byte*)((Int64)pointer + offset + capacity)) < pointer)
-                    {
-                        throw new ArgumentException(SR.Argument_UnmanagedMemAccessorWrapAround);
-                    }
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            _offset = offset;
-            _buffer = buffer;
-            _capacity = capacity;
-            _access = access;
-            _isOpen = true;
-            _canRead = (_access & FileAccess.Read) != 0;
-            _canWrite = (_access & FileAccess.Write) != 0;
-        }
-
-        #endregion
-
-        public Int64 Capacity
-        {
-            get
-            {
-                return _capacity;
-            }
-        }
-
-        public bool CanRead
-        {
-            get
-            {
-                return _isOpen && _canRead;
-            }
-        }
-
-        public bool CanWrite
-        {
-            get
-            {
-                return _isOpen && _canWrite;
-            }
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            _isOpen = false;
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        protected bool IsOpen
-        {
-            get { return _isOpen; }
-        }
-
-        public bool ReadBoolean(Int64 position)
-        {
-            int sizeOfType = sizeof(bool);
-            EnsureSafeToRead(position, sizeOfType);
-
-            byte b = InternalReadByte(position);
-            return b != 0;
-        }
-
-        public byte ReadByte(Int64 position)
-        {
-            int sizeOfType = sizeof(byte);
-            EnsureSafeToRead(position, sizeOfType);
-
-            return InternalReadByte(position);
-        }
-
-        public char ReadChar(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(char));
-
-            char result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<char>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        // See comment above.
-        public Int16 ReadInt16(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(Int16));
-
-            Int16 result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<Int16>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-
-        public Int32 ReadInt32(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(Int32));
-
-            Int32 result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<Int32>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        public Int64 ReadInt64(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(Int64));
-
-            Int64 result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<Int64>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        public Decimal ReadDecimal(Int64 position)
-        {
-            const int ScaleMask = 0x00FF0000;
-            const int SignMask = unchecked((int)0x80000000);
-
-            EnsureSafeToRead(position, sizeof(Decimal));
-
-            int lo, mid, hi, flags;
-
-            unsafe
-            {
-                byte* pointer = null;
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    
-                    lo = Unsafe.ReadUnaligned<Int32>(pointer + _offset + position);
-                    mid = Unsafe.ReadUnaligned<Int32>(pointer + _offset + position + 4);
-                    hi = Unsafe.ReadUnaligned<Int32>(pointer + _offset + position + 8);
-                    flags = Unsafe.ReadUnaligned<Int32>(pointer + _offset + position + 12);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            // Check for invalid Decimal values
-            if (!((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)))
-            {
-                throw new ArgumentException(SR.Arg_BadDecimal); // Throw same Exception type as Decimal(int[]) ctor for compat
-            }
-
-            bool isNegative = (flags & SignMask) != 0;
-            byte scale = (byte)(flags >> 16);
-
-            return new decimal(lo, mid, hi, isNegative, scale);
-        }
-
-        public Single ReadSingle(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(Single));
-
-            Single result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<Single>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        public Double ReadDouble(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(Double));
-
-            Double result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<Double>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        [CLSCompliant(false)]
-        public SByte ReadSByte(Int64 position)
-        {
-            int sizeOfType = sizeof(SByte);
-            EnsureSafeToRead(position, sizeOfType);
-
-            SByte result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = *((SByte*)(pointer + _offset + position));
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        [CLSCompliant(false)]
-        public UInt16 ReadUInt16(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(UInt16));
-
-            UInt16 result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<UInt16>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        [CLSCompliant(false)]
-        public UInt32 ReadUInt32(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(UInt32));
-
-            UInt32 result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<UInt32>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        [CLSCompliant(false)]
-        public UInt64 ReadUInt64(Int64 position)
-        {
-            EnsureSafeToRead(position, sizeof(UInt64));
-
-            UInt64 result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = Unsafe.ReadUnaligned<UInt64>(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        // Reads a struct of type T from unmanaged memory, into the reference pointed to by ref value.  
-        // Note: this method is not safe, since it overwrites the contents of a structure, it can be 
-        // used to modify the private members of a struct.  Furthermore, using this with a struct that
-        // contains reference members will most likely cause the runtime to AV.  Note, that despite 
-        // various checks made by the C++ code used by Marshal.PtrToStructure, Marshal.PtrToStructure
-        // will still overwrite privates and will also crash the runtime when used with structs 
-        // containing reference members.  For this reason, I am sticking an UnmanagedCode requirement
-        // on this method to match Marshal.PtrToStructure.
-
-        // Alos note that this method is most performant when used with medium to large sized structs
-        // (larger than 8 bytes -- though this is number is JIT and architecture dependent).   As 
-        // such, it is best to use the ReadXXX methods for small standard types such as ints, longs, 
-        // bools, etc.
-
-        public void Read<T>(Int64 position, out T structure) where T : struct
-        {
-            if (position < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            if (!_isOpen)
-            {
-                throw new ObjectDisposedException("UnmanagedMemoryAccessor", SR.ObjectDisposed_ViewAccessorClosed);
-            }
-            if (!CanRead)
-            {
-                throw new NotSupportedException(SR.NotSupported_Reading);
-            }
-
-            UInt32 sizeOfT = Marshal.SizeOfType(typeof(T));
-            if (position > _capacity - sizeOfT)
-            {
-                if (position >= _capacity)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
-                }
-                else
-                {
-                    throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToRead, typeof (T).FullName), nameof(position));
-                }
-            }
-
-            structure = _buffer.Read<T>((UInt64)(_offset + position));
-        }
-
-        // Reads 'count' structs of type T from unmanaged memory, into 'array' starting at 'offset'.  
-        // Note: this method is not safe, since it overwrites the contents of structures, it can 
-        // be used to modify the private members of a struct.  Furthermore, using this with a 
-        // struct that contains reference members will most likely cause the runtime to AV. This
-        // is consistent with Marshal.PtrToStructure.
-
-        public int ReadArray<T>(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct
-        {
-            if (array == null)
-            {
-                throw new ArgumentNullException(nameof(array), "Buffer cannot be null.");
-            }
-            if (offset < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (count < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (array.Length - offset < count)
-            {
-                throw new ArgumentException(SR.Argument_OffsetAndLengthOutOfBounds);
-            }
-            if (!CanRead)
-            {
-                if (!_isOpen)
-                {
-                    throw new ObjectDisposedException("UnmanagedMemoryAccessor", SR.ObjectDisposed_ViewAccessorClosed);
-                }
-                else
-                {
-                    throw new NotSupportedException(SR.NotSupported_Reading);
-                }
-            }
-            if (position < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            UInt32 sizeOfT = Marshal.AlignedSizeOf<T>();
-
-            // only check position and ask for fewer Ts if count is too big
-            if (position >= _capacity)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
-            }
-
-            int n = count;
-            long spaceLeft = _capacity - position;
-            if (spaceLeft < 0)
-            {
-                n = 0;
-            }
-            else
-            {
-                ulong spaceNeeded = (ulong)(sizeOfT * count);
-                if ((ulong)spaceLeft < spaceNeeded)
-                {
-                    n = (int)(spaceLeft / sizeOfT);
-                }
-            }
-
-            _buffer.ReadArray<T>((UInt64)(_offset + position), array, offset, n);
-
-            return n;
-        }
-
-        // ************** Write Methods ****************/
-
-        // The following 13 WriteXXX methods write a value of type XXX into unmanaged memory at 'positon'. 
-        // The bounds of the unmanaged memory are checked against to ensure that there is enough 
-        // space after 'position' to write a value of type XXX.  XXX can be a bool, byte, char, decimal, 
-        // double, short, int, long, sbyte, float, ushort, uint, or ulong. 
-
-
-        public void Write(Int64 position, bool value)
-        {
-            int sizeOfType = sizeof(bool);
-            EnsureSafeToWrite(position, sizeOfType);
-
-            byte b = (byte)(value ? 1 : 0);
-            InternalWrite(position, b);
-        }
-
-        public void Write(Int64 position, byte value)
-        {
-            int sizeOfType = sizeof(byte);
-            EnsureSafeToWrite(position, sizeOfType);
-
-            InternalWrite(position, value);
-        }
-
-        public void Write(Int64 position, char value)
-        {
-            EnsureSafeToWrite(position, sizeof(char));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<char>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-
-        public void Write(Int64 position, Int16 value)
-        {
-            EnsureSafeToWrite(position, sizeof(Int16));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<Int16>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-
-        public void Write(Int64 position, Int32 value)
-        {
-            EnsureSafeToWrite(position, sizeof(Int32));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<Int32>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        public void Write(Int64 position, Int64 value)
-        {
-            EnsureSafeToWrite(position, sizeof(Int64));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<Int64>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        public void Write(Int64 position, Decimal value)
-        {
-            EnsureSafeToWrite(position, sizeof(Decimal));
-
-            unsafe
-            {
-                int* valuePtr = (int*)(&value);
-                int flags = *valuePtr;
-                int hi = *(valuePtr + 1);
-                int lo = *(valuePtr + 2);
-                int mid = *(valuePtr + 3);
-
-                byte* pointer = null;
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-
-                    Unsafe.WriteUnaligned<Int32>(pointer + _offset + position, lo);
-                    Unsafe.WriteUnaligned<Int32>(pointer + _offset + position + 4, mid);
-                    Unsafe.WriteUnaligned<Int32>(pointer + _offset + position + 8, hi);
-                    Unsafe.WriteUnaligned<Int32>(pointer + _offset + position + 12, flags);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        public void Write(Int64 position, Single value)
-        {
-            EnsureSafeToWrite(position, sizeof(Single));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<Single>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        public void Write(Int64 position, Double value)
-        {
-            EnsureSafeToWrite(position, sizeof(Double));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<Double>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        [CLSCompliant(false)]
-        public void Write(Int64 position, SByte value)
-        {
-            EnsureSafeToWrite(position, sizeof(SByte));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    *((SByte*)(pointer + _offset + position)) = value;
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        [CLSCompliant(false)]
-        public void Write(Int64 position, UInt16 value)
-        {
-            int sizeOfType = sizeof(UInt16);
-            EnsureSafeToWrite(position, sizeOfType);
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<UInt16>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        [CLSCompliant(false)]
-        public void Write(Int64 position, UInt32 value)
-        {
-            EnsureSafeToWrite(position, sizeof(UInt32));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<UInt32>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        [CLSCompliant(false)]
-        public void Write(Int64 position, UInt64 value)
-        {
-            EnsureSafeToWrite(position, sizeof(UInt64));
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    Unsafe.WriteUnaligned<UInt64>(pointer + _offset + position, value);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        // Writes the struct pointed to by ref value into unmanaged memory.  Note that this method
-        // is most performant when used with medium to large sized structs (larger than 8 bytes 
-        // though this is number is JIT and architecture dependent).   As such, it is best to use 
-        // the WriteX methods for small standard types such as ints, longs, bools, etc.
-
-        public void Write<T>(Int64 position, ref T structure) where T : struct
-        {
-            if (position < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            if (!_isOpen)
-            {
-                throw new ObjectDisposedException("UnmanagedMemoryAccessor", SR.ObjectDisposed_ViewAccessorClosed);
-            }
-            if (!CanWrite)
-            {
-                throw new NotSupportedException(SR.NotSupported_Writing);
-            }
-
-            UInt32 sizeOfT = Marshal.SizeOfType(typeof(T));
-            if (position > _capacity - sizeOfT)
-            {
-                if (position >= _capacity)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
-                }
-                else
-                {
-                    throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToWrite, typeof (T).FullName), nameof(position));
-                }
-            }
-
-            _buffer.Write<T>((UInt64)(_offset + position), structure);
-        }
-
-        // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory. 
-
-
-        public void WriteArray<T>(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct
-        {
-            if (array == null)
-            {
-                throw new ArgumentNullException(nameof(array), "Buffer cannot be null.");
-            }
-            if (offset < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (count < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (array.Length - offset < count)
-            {
-                throw new ArgumentException(SR.Argument_OffsetAndLengthOutOfBounds);
-            }
-            if (position < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (position >= Capacity)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
-            }
-
-            if (!_isOpen)
-            {
-                throw new ObjectDisposedException("UnmanagedMemoryAccessor", SR.ObjectDisposed_ViewAccessorClosed);
-            }
-            if (!CanWrite)
-            {
-                throw new NotSupportedException(SR.NotSupported_Writing);
-            }
-
-            _buffer.WriteArray<T>((UInt64)(_offset + position), array, offset, count);
-        }
-
-        private byte InternalReadByte(Int64 position)
-        {
-            Debug.Assert(CanRead, "UMA not readable");
-            Debug.Assert(position >= 0, "position less than 0");
-            Debug.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
-
-            byte result;
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    result = *(pointer + _offset + position);
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-            return result;
-        }
-
-        private void InternalWrite(Int64 position, byte value)
-        {
-            Debug.Assert(CanWrite, "UMA not writable");
-            Debug.Assert(position >= 0, "position less than 0");
-            Debug.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
-
-            unsafe
-            {
-                byte* pointer = null;
-                RuntimeHelpers.PrepareConstrainedRegions();
-                try
-                {
-                    _buffer.AcquirePointer(ref pointer);
-                    *(pointer + _offset + position) = value;
-                }
-                finally
-                {
-                    if (pointer != null)
-                    {
-                        _buffer.ReleasePointer();
-                    }
-                }
-            }
-        }
-
-        private void EnsureSafeToRead(Int64 position, int sizeOfType)
-        {
-            if (!_isOpen)
-            {
-                throw new ObjectDisposedException("UnmanagedMemoryAccessor", SR.ObjectDisposed_ViewAccessorClosed);
-            }
-            if (!CanRead)
-            {
-                throw new NotSupportedException(SR.NotSupported_Reading);
-            }
-            if (position < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (position > _capacity - sizeOfType)
-            {
-                if (position >= _capacity)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
-                }
-                else
-                {
-                    throw new ArgumentException(SR.Argument_NotEnoughBytesToRead, nameof(position));
-                }
-            }
-        }
-
-        private void EnsureSafeToWrite(Int64 position, int sizeOfType)
-        {
-            if (!_isOpen)
-            {
-                throw new ObjectDisposedException("UnmanagedMemoryAccessor", SR.ObjectDisposed_ViewAccessorClosed);
-            }
-            if (!CanWrite)
-            {
-                throw new NotSupportedException(SR.NotSupported_Writing);
-            }
-            if (position < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-            if (position > _capacity - sizeOfType)
-            {
-                if (position >= _capacity)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(position), SR.ArgumentOutOfRange_PositionLessThanCapacityRequired);
-                }
-                else
-                {
-                    throw new ArgumentException(SR.Format(SR.Argument_NotEnoughBytesToWrite, nameof(Byte)), nameof(position));
-                }
-            }
-        }
-    }
-}
index efa5125..98b33e3 100644 (file)
@@ -256,35 +256,6 @@ namespace System.Runtime.InteropServices
             return SizeOf(typeof(T));
         }
 
-        /// <summary>
-        /// Returns the aligned size of an instance of a value type.
-        /// </summary>
-        /// <typeparam name="T">Provide a value type to figure out its size</typeparam>
-        /// <returns>The aligned size of T in bytes.</returns>
-        internal static uint AlignedSizeOf<T>() where T : struct
-        {
-            uint size = SizeOfType(typeof(T));
-            if (size == 1 || size == 2)
-            {
-                return size;
-            }
-            if (IntPtr.Size == 8 && size == 4)
-            {
-                return size;
-            }
-            return AlignedSizeOfType(typeof(T));
-        }
-
-        // Type must be a value type with no object reference fields.  We only
-        // assert this, due to the lack of a suitable generic constraint.
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern uint SizeOfType(Type type);
-
-        // Type must be a value type with no object reference fields.  We only
-        // assert this, due to the lack of a suitable generic constraint.
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern uint AlignedSizeOfType(Type type);
-
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
         internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable);
 
index 4f97875..0447ea5 100644 (file)
@@ -129,7 +129,7 @@ namespace System.Runtime.InteropServices
         [CLSCompliant(false)]
         public void Initialize<T>(uint numElements) where T : struct
         {
-            Initialize(numElements, Marshal.AlignedSizeOf<T>());
+            Initialize(numElements, AlignedSizeOf<T>());
         }
 
         // Callers should ensure that they check whether the pointer ref param
@@ -198,7 +198,7 @@ namespace System.Runtime.InteropServices
             if (_numBytes == Uninitialized)
                 throw NotInitialized();
 
-            uint sizeofT = Marshal.SizeOfType(typeof(T));
+            uint sizeofT = SizeOf<T>();
             byte* ptr = (byte*)handle + byteOffset;
             SpaceCheck(ptr, sizeofT);
 
@@ -236,8 +236,8 @@ namespace System.Runtime.InteropServices
             if (_numBytes == Uninitialized)
                 throw NotInitialized();
 
-            uint sizeofT = Marshal.SizeOfType(typeof(T));
-            uint alignedSizeofT = Marshal.AlignedSizeOf<T>();
+            uint sizeofT = SizeOf<T>();
+            uint alignedSizeofT = AlignedSizeOf<T>();
             byte* ptr = (byte*)handle + byteOffset;
             SpaceCheck(ptr, checked((ulong)(alignedSizeofT * count)));
 
@@ -271,7 +271,7 @@ namespace System.Runtime.InteropServices
             if (_numBytes == Uninitialized)
                 throw NotInitialized();
 
-            uint sizeofT = Marshal.SizeOfType(typeof(T));
+            uint sizeofT = SizeOf<T>();
             byte* ptr = (byte*)handle + byteOffset;
             SpaceCheck(ptr, sizeofT);
 
@@ -306,8 +306,8 @@ namespace System.Runtime.InteropServices
             if (_numBytes == Uninitialized)
                 throw NotInitialized();
 
-            uint sizeofT = Marshal.SizeOfType(typeof(T));
-            uint alignedSizeofT = Marshal.AlignedSizeOf<T>();
+            uint sizeofT = SizeOf<T>();
+            uint alignedSizeofT = AlignedSizeOf<T>();
             byte* ptr = (byte*)handle + byteOffset;
             SpaceCheck(ptr, checked((ulong)(alignedSizeofT * count)));
 
@@ -381,5 +381,44 @@ namespace System.Runtime.InteropServices
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void StructureToPtrNative(/*ref T*/ TypedReference structure, byte* ptr, uint sizeofT);
+
+        /// <summary>
+        /// Returns the aligned size of an instance of a value type.
+        /// </summary>
+        /// <typeparam name="T">Provide a value type to figure out its size</typeparam>
+        /// <returns>The aligned size of T in bytes.</returns>
+        internal static uint SizeOf<T>() where T : struct
+        {
+            return SizeOfType(typeof(T));
+        }
+
+        /// <summary>
+        /// Returns the aligned size of an instance of a value type.
+        /// </summary>
+        /// <typeparam name="T">Provide a value type to figure out its size</typeparam>
+        /// <returns>The aligned size of T in bytes.</returns>
+        internal static uint AlignedSizeOf<T>() where T : struct
+        {
+            uint size = SizeOfType(typeof(T));
+            if (size == 1 || size == 2)
+            {
+                return size;
+            }
+            if (IntPtr.Size == 8 && size == 4)
+            {
+                return size;
+            }
+            return AlignedSizeOfType(typeof(T));
+        }
+
+        // Type must be a value type with no object reference fields.  We only
+        // assert this, due to the lack of a suitable generic constraint.
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern uint SizeOfType(Type type);
+
+        // Type must be a value type with no object reference fields.  We only
+        // assert this, due to the lack of a suitable generic constraint.
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern uint AlignedSizeOfType(Type type);
     }
 }
index 4ee9826..207e89a 100644 (file)
@@ -201,6 +201,8 @@ FCFuncEnd()
 FCFuncStart(gSafeBufferFuncs)
     FCFuncElement("PtrToStructureNative", SafeBuffer::PtrToStructure)
     FCFuncElement("StructureToPtrNative", SafeBuffer::StructureToPtr)
+    FCFuncElement("SizeOfType", SafeBuffer::SizeOfType)
+    FCFuncElement("AlignedSizeOfType", SafeBuffer::AlignedSizeOfType)
 FCFuncEnd()
 
 FCFuncStart(gTypedReferenceFuncs)
@@ -894,8 +896,6 @@ FCFuncStart(gInteropMarshalFuncs)
     QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE)
 
     FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper)
-    FCFuncElement("SizeOfType", SafeBuffer::SizeOfType)
-    FCFuncElement("AlignedSizeOfType", SafeBuffer::AlignedSizeOfType)
 
     QCFuncElement("InternalPrelink", MarshalNative::Prelink)
     FCFuncElement("CopyToNative", MarshalNative::CopyToNative)