Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
Avoid unnecessary branches when fixing non-null/empty arrays (#2668)
Browse files Browse the repository at this point in the history
When we know an array is not null or empty at the point where fixed is
used, we can reduce the number of branches (and IL size of the method
body) by using the address of the first element.
  • Loading branch information
justinvp authored and jkotas committed Feb 5, 2017
1 parent 6528a62 commit a086b1c
Show file tree
Hide file tree
Showing 22 changed files with 69 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal static unsafe string GetCwd()
{
checked { bufferSize *= 2; }
var buf = new byte[Math.Min(bufferSize, maxPath)];
fixed (byte* ptr = buf)
fixed (byte* ptr = &buf[0])
{
result = GetCwdHelper(ptr, buf.Length);
if (result != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal static unsafe byte[] StringToAnsi(String str)
int stringLength = str.Length;
int bufferLength = encoding.GetByteCount(pStr, stringLength);
var buffer = new byte[bufferLength + 1];
fixed (byte* pBuffer = buffer)
fixed (byte* pBuffer = &buffer[0])
{
encoding.GetBytes(pStr, stringLength, pBuffer, bufferLength);
return buffer;
Expand Down
32 changes: 20 additions & 12 deletions src/System.Private.CoreLib/src/System/Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2532,18 +2532,22 @@ public unsafe Object GetValue(params int[] indices)
if (indices == null)
throw new ArgumentNullException(nameof(indices));

if (IsSzArray && indices.Length == 1)
int length = indices.Length;

if (IsSzArray && length == 1)
return GetValue(indices[0]);

fixed (int* pIndices = indices)
return GetValue(pIndices, indices.Length);
if (Rank != length)
throw new ArgumentException(SR.Arg_RankIndices);

Debug.Assert(length > 0);
fixed (int* pIndices = &indices[0])
return GetValue(pIndices, length);
}

private unsafe Object GetValue(int* pIndices, int rank)
{
if (this.Rank != rank)
throw new ArgumentException(SR.Arg_RankIndices);

Debug.Assert(Rank == rank);
Debug.Assert(!IsSzArray);

fixed (IntPtr* pThisArray = &m_pEEType)
Expand Down Expand Up @@ -2662,24 +2666,28 @@ public unsafe void SetValue(Object value, params int[] indices)
if (indices == null)
throw new ArgumentNullException(nameof(indices));

if (IsSzArray && indices.Length == 1)
int length = indices.Length;

if (IsSzArray && length == 1)
{
SetValue(value, indices[0]);
return;
}

fixed (int* pIndices = indices)
if (Rank != length)
throw new ArgumentException(SR.Arg_RankIndices);

Debug.Assert(length > 0);
fixed (int* pIndices = &indices[0])
{
SetValue(value, pIndices, indices.Length);
SetValue(value, pIndices, length);
return;
}
}

private unsafe void SetValue(Object value, int* pIndices, int rank)
{
if (this.Rank != rank)
throw new ArgumentException(SR.Arg_RankIndices);

Debug.Assert(Rank == rank);
Debug.Assert(!IsSzArray);

fixed (IntPtr* pThisArray = &m_pEEType)
Expand Down
6 changes: 3 additions & 3 deletions src/System.Private.CoreLib/src/System/Convert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2392,7 +2392,7 @@ internal static unsafe String ToBase64String(byte[] inArray, int offset, int len
string returnString = new string('\0', stringLength);
fixed (char* outChars = returnString)
{
fixed (byte* inData = inArray)
fixed (byte* inData = &inArray[0])
{
int j = ConvertToBase64Array(outChars, inData, offset, length, insertLineBreaks);
System.Diagnostics.Debug.Assert(returnString.Length == j, "returnString.Length == j");
Expand Down Expand Up @@ -2459,7 +2459,7 @@ internal static unsafe int ToBase64CharArray(byte[] inArray, int offsetIn, int l

fixed (char* outChars = &outArray[offsetOut])
{
fixed (byte* inData = inArray)
fixed (byte* inData = &inArray[0])
{
retVal = ConvertToBase64Array(outChars, inData, offsetIn, length, insertLineBreaks);
}
Expand All @@ -2478,7 +2478,7 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int
int i;

// get a pointer to the base64Table to avoid unnecessary range checking
fixed (char* base64 = base64Table)
fixed (char* base64 = &base64Table[0])
{
for (i = offset; i < calcLength; i += 3)
{
Expand Down
2 changes: 1 addition & 1 deletion src/System.Private.CoreLib/src/System/Environment.Win32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static unsafe String GetEnvironmentVariable(String variable)
currentSize = requiredSize;
// need to retry since the environment variable might be changed
newblob = new char[currentSize];
fixed (char* pText = variable, pBlob = newblob)
fixed (char* pText = variable, pBlob = &newblob[0])
{
requiredSize = Interop.mincore.GetEnvironmentVariable(pText, pBlob, currentSize);
}
Expand Down
2 changes: 1 addition & 1 deletion src/System.Private.CoreLib/src/System/Exception.cs
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ internal unsafe byte[] SerializeForDump()
int cbBuffer = sizeof(SERIALIZED_EXCEPTION_HEADER) + (nStackTraceElements * IntPtr.Size);

byte[] buffer = new byte[cbBuffer];
fixed (byte* pBuffer = buffer)
fixed (byte* pBuffer = &buffer[0])
{
SERIALIZED_EXCEPTION_HEADER* pHeader = (SERIALIZED_EXCEPTION_HEADER*)pBuffer;
pHeader->HResult = _HResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ internal static unsafe double InternalGetNumericValue(int ch)
fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index]))
{
byte* pBytePtr = (byte*)pUshortPtr;
fixed (byte* pByteNum = s_pNumericValues)
fixed (byte* pByteNum = &s_pNumericValues[0])
{
double* pDouble = (double*)pByteNum;
return pDouble[pBytePtr[(ch & 0x000f)]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ internal unsafe int GetHashCodeOfStringCore(string source, CompareOptions option

byte[] sortKey = new byte[sortKeyLength];

fixed(byte* pSortKey = sortKey)
fixed (byte* pSortKey = &sortKey[0])
{
Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
return InternalHashSortKey(pSortKey, sortKeyLength, false, additionalEntropy);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ internal static unsafe void FormatDigits(StringBuilder outputBuffer, int value,
int digits;

char[] charBuff = new char[16];
fixed (char* buffer = charBuff)
fixed (char* buffer = &charBuff[0])
{
char* p = buffer + 16;
int n = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ private unsafe string GetAsciiCore(char* unicode, int count)
}

char[] outputHeap = new char[actualLength];
fixed (char* pOutputHeap = outputHeap)
fixed (char* pOutputHeap = &outputHeap[0])
{
actualLength = Interop.GlobalizationInterop.ToAscii(flags, unicode, count, pOutputHeap, actualLength);
if (actualLength == 0 || actualLength > outputHeap.Length)
Expand All @@ -60,7 +60,7 @@ private unsafe string GetUnicodeCore(char* ascii, int count)
else
{
char[] output = new char[count];
fixed (char* pOutput = output)
fixed (char* pOutput = &output[0])
{
return GetUnicodeCore(ascii, count, flags, pOutput, count, reattempt: true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private unsafe string GetAsciiCore(char* unicode, int count)
else
{
char[] output = new char[length];
fixed (char* pOutput = output)
fixed (char* pOutput = &output[0])
{
return GetAsciiCore(unicode, count, flags, pOutput, length);
}
Expand Down Expand Up @@ -69,7 +69,7 @@ private unsafe string GetUnicodeCore(char* ascii, int count)
else
{
char[] output = new char[length];
fixed (char* pOutput = output)
fixed (char* pOutput = &output[0])
{
return GetUnicodeCore(ascii, count, flags, pOutput, length);
}
Expand Down
4 changes: 2 additions & 2 deletions src/System.Private.CoreLib/src/System/IO/FileStream.Win32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offse
int r = 0;
int numBytesRead = 0;

fixed (byte* p = bytes)
fixed (byte* p = &bytes[0])
{
if (_useAsyncIO)
r = Interop.mincore.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped);
Expand Down Expand Up @@ -1329,7 +1329,7 @@ private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offs
int numBytesWritten = 0;
int r = 0;

fixed (byte* p = bytes)
fixed (byte* p = &bytes[0])
{
if (_useAsyncIO)
r = Interop.mincore.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ internal static byte[] ConvertPublicKeyToPublicKeyToken(byte[] publicKey)
{
fixed (byte* pPublicKey = publicKey)
{
fixed (byte* pPublicKeyToken = publicKeyToken)
fixed (byte* pPublicKeyToken = &publicKeyToken[0])
{
RhConvertPublicKeyToPublicKeyToken(pPublicKey, publicKey.Length, pPublicKeyToken, publicKeyToken.Length);
}
Expand Down
12 changes: 7 additions & 5 deletions src/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public unsafe byte[] Serialize()
checked
{
byte[] serializedData = new byte[sizeof(ExceptionMetadataStruct) + SerializedExceptionData.Length];
fixed (byte* pSerializedData = serializedData)
fixed (byte* pSerializedData = &serializedData[0])
{
ExceptionMetadataStruct* pMetadata = (ExceptionMetadataStruct*)pSerializedData;
pMetadata->ExceptionId = ExceptionMetadata.ExceptionId;
Expand Down Expand Up @@ -538,7 +538,7 @@ private static unsafe void GenerateErrorReportForDump(LowLevelList<byte[]> seria
}

byte[] finalBuffer = new byte[cbFinalBuffer];
fixed (byte* pBuffer = finalBuffer)
fixed (byte* pBuffer = &finalBuffer[0])
{
byte* pCursor = pBuffer;
int cbRemaining = cbFinalBuffer;
Expand Down Expand Up @@ -593,17 +593,19 @@ public static bool SafeToPerformRichExceptionSupport

private static unsafe void UpdateErrorReportBuffer(byte[] finalBuffer)
{
Debug.Assert(finalBuffer?.Length > 0);

using (LockHolder.Hold(s_ExceptionInfoBufferLock))
{
fixed (byte* pBuffer = finalBuffer)
fixed (byte* pBuffer = &finalBuffer[0])
{
byte* pPrevBuffer = (byte*)RuntimeImports.RhSetErrorInfoBuffer(pBuffer);
Debug.Assert(s_ExceptionInfoBufferPinningHandle.IsAllocated == (pPrevBuffer != null));
if (pPrevBuffer != null)
{
byte[] currentExceptionInfoBuffer = (byte[])s_ExceptionInfoBufferPinningHandle.Target;
Debug.Assert(currentExceptionInfoBuffer != null);
fixed (byte* pPrev = currentExceptionInfoBuffer)
Debug.Assert(currentExceptionInfoBuffer?.Length > 0);
fixed (byte* pPrev = &currentExceptionInfoBuffer[0])
Debug.Assert(pPrev == pPrevBuffer);
}
if (!s_ExceptionInfoBufferPinningHandle.IsAllocated)
Expand Down
4 changes: 2 additions & 2 deletions src/System.Private.CoreLib/src/System/String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ unsafe public char[] ToCharArray()
{
char[] chars = new char[length];
fixed (char* src = &_firstChar)
fixed (char* dest = chars)
fixed (char* dest = &chars[0])
{
wstrcpy(dest, src, length);
}
Expand All @@ -373,7 +373,7 @@ unsafe public char[] ToCharArray(int startIndex, int length)
{
char[] chars = new char[length];
fixed (char* src = &_firstChar)
fixed (char* dest = chars)
fixed (char* dest = &chars[0])
{
wstrcpy(dest, src + startIndex, length);
}
Expand Down
10 changes: 5 additions & 5 deletions src/System.Private.CoreLib/src/System/Text/DecoderNLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public override unsafe int GetCharCount(byte[] bytes, int index, int count, bool
bytes = new byte[1];

// Just call pointer version
fixed (byte* pBytes = bytes)
fixed (byte* pBytes = &bytes[0])
return GetCharCount(pBytes + index, count, flush);
}

Expand Down Expand Up @@ -136,8 +136,8 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
chars = new char[1];

// Just call pointer version
fixed (byte* pBytes = bytes)
fixed (char* pChars = chars)
fixed (byte* pBytes = &bytes[0])
fixed (char* pChars = &chars[0])
// Remember that charCount is # to decode, not size of array
return GetChars(pBytes + byteIndex, byteCount,
pChars + charIndex, charCount, flush);
Expand Down Expand Up @@ -200,9 +200,9 @@ public override unsafe void Convert(byte[] bytes, int byteIndex, int byteCount,
chars = new char[1];

// Just call the pointer version (public overrides can't do this)
fixed (byte* pBytes = bytes)
fixed (byte* pBytes = &bytes[0])
{
fixed (char* pChars = chars)
fixed (char* pChars = &chars[0])
{
Convert(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, flush,
out bytesUsed, out charsUsed, out completed);
Expand Down
10 changes: 5 additions & 5 deletions src/System.Private.CoreLib/src/System/Text/EncoderNLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public override unsafe int GetByteCount(char[] chars, int index, int count, bool

// Just call the pointer version
int result = -1;
fixed (char* pChars = chars)
fixed (char* pChars = &chars[0])
{
result = GetByteCount(pChars + index, count, flush);
}
Expand Down Expand Up @@ -127,8 +127,8 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
bytes = new byte[1];

// Just call pointer version
fixed (char* pChars = chars)
fixed (byte* pBytes = bytes)
fixed (char* pChars = &chars[0])
fixed (byte* pBytes = &bytes[0])

// Remember that charCount is # to decode, not size of array.
return GetBytes(pChars + charIndex, charCount,
Expand Down Expand Up @@ -188,9 +188,9 @@ public override unsafe void Convert(char[] chars, int charIndex, int charCount,
bytes = new byte[1];

// Just call the pointer version (can't do this for non-msft encoders)
fixed (char* pChars = chars)
fixed (char* pChars = &chars[0])
{
fixed (byte* pBytes = bytes)
fixed (byte* pBytes = &bytes[0])
{
Convert(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, flush,
out charsUsed, out bytesUsed, out completed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static unsafe int GetBytes(Encoding encoding, string s, int charIndex, in
if (bytes.Length == 0)
bytes = new byte[1];

fixed (char* pChars = s) fixed (byte* pBytes = bytes)
fixed (char* pChars = s) fixed (byte* pBytes = &bytes[0])
{
return encoding.GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, encoder: null);
}
Expand Down Expand Up @@ -169,7 +169,7 @@ public static unsafe int GetBytes(Encoding encoding, char[] chars, int charIndex
bytes = new byte[1];

// Just call the (internal) pointer version
fixed (char* pChars = chars) fixed (byte* pBytes = bytes)
fixed (char* pChars = chars) fixed (byte* pBytes = &bytes[0])
{
return encoding.GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, encoder: null);
}
Expand Down Expand Up @@ -265,7 +265,7 @@ public static unsafe int GetChars(Encoding encoding, byte[] bytes, int byteIndex
if (chars.Length == 0)
chars = new char[1];

fixed (byte* pBytes = bytes) fixed (char* pChars = chars)
fixed (byte* pBytes = bytes) fixed (char* pChars = &chars[0])
{
return encoding.GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, decoder: null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// always manually marshal the arguments

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

Expand Down Expand Up @@ -90,10 +91,11 @@ internal static extern unsafe int FormatMessage(
/// <returns>Return false IFF when buffer space isnt enough</returns>
private static unsafe bool TryGetMessage(int errorCode, int bufferSize, out string errorMsg)
{
Debug.Assert(bufferSize > 0);
errorMsg = null;
char[] buffer = new char[bufferSize];
int result;
fixed (char* pinned_lpBuffer = buffer)
fixed (char* pinned_lpBuffer = &buffer[0])
{
result = ExternalInterop.FormatMessage(
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM |
Expand Down
Loading

0 comments on commit a086b1c

Please sign in to comment.