Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ internal static void UnregisterMemoryLoadChangeNotification(Action notification)
/// If pinned is set to true, <typeparamref name="T"/> must not be a reference type or a type that contains object references.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)] // forced to ensure no perf drop for small memory buffers (hot path)
public static T[] AllocateUninitializedArray<T>(int length, bool pinned = false) // T[] rather than T?[] to match `new T[length]` behavior
public static unsafe T[] AllocateUninitializedArray<T>(int length, bool pinned = false) // T[] rather than T?[] to match `new T[length]` behavior
{
if (!pinned)
{
Expand All @@ -689,10 +689,13 @@ public static T[] AllocateUninitializedArray<T>(int length, bool pinned = false)
// for debug builds we always want to call AllocateNewArray to detect AllocateNewArray bugs
#if !DEBUG
// small arrays are allocated using `new[]` as that is generally faster.
if (length < 2048 / Unsafe.SizeOf<T>())
#pragma warning disable 8500 // sizeof of managed types
if (length < 2048 / sizeof(T))
#pragma warning restore 8500
{
return new T[length];
}

#endif
}
else if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,12 @@ public void Dispose()
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern object? InternalGetTarget(IntPtr dependentHandle);
#else
private static unsafe object? InternalGetTarget(IntPtr dependentHandle)
{
// This optimization is the same that is used in GCHandle in RELEASE mode.
// This is not used in DEBUG builds as the runtime performs additional checks.
// The logic below is the inlined copy of ObjectFromHandle in the unmanaged runtime.
return Unsafe.As<IntPtr, object>(ref *(IntPtr*)(nint)dependentHandle);
}
// This optimization is the same that is used in GCHandle in RELEASE mode.
// This is not used in DEBUG builds as the runtime performs additional checks.
// The logic below is the inlined copy of ObjectFromHandle in the unmanaged runtime.
#pragma warning disable 8500 // address of managed types
private static unsafe object? InternalGetTarget(IntPtr dependentHandle) => *(object*)dependentHandle;
#pragma warning restore 8500
#endif

[MethodImpl(MethodImplOptions.InternalCall)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public partial struct GCHandle
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object? InternalGet(IntPtr handle);
#else
internal static unsafe object? InternalGet(IntPtr handle) =>
Unsafe.As<IntPtr, object>(ref *(IntPtr*)(nint)handle);
#pragma warning disable 8500 // address of managed types
internal static unsafe object? InternalGet(IntPtr handle) => *(object*)handle;
#pragma warning restore 8500
#endif

[MethodImpl(MethodImplOptions.InternalCall)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ internal static unsafe class CachedInterfaceDispatch
private static unsafe IntPtr RhpCidResolve(IntPtr callerTransitionBlockParam, IntPtr pCell)
{
IntPtr locationOfThisPointer = callerTransitionBlockParam + TransitionBlock.GetThisOffset();
object pObject = Unsafe.As<IntPtr, object>(ref *(IntPtr*)locationOfThisPointer);
#pragma warning disable 8500 // address of managed types
object pObject = *(object*)locationOfThisPointer;
#pragma warning restore 8500
IntPtr dispatchResolveTarget = RhpCidResolve_Worker(pObject, pCell);
return dispatchResolveTarget;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ public unsafe object Target
// The runtime performs additional checks in debug builds
return InternalCalls.RhHandleGet(_handle);
#else
return Unsafe.As<IntPtr, object>(ref *(IntPtr*)_handle);
#pragma warning disable 8500 // address of managed types
return *(object*)_handle;
#pragma warning restore 8500
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,9 @@ public static unsafe T[] AllocateUninitializedArray<T>(int length, bool pinned =
// for debug builds we always want to call AllocateNewArray to detect AllocateNewArray bugs
#if !DEBUG
// small arrays are allocated using `new[]` as that is generally faster.
if (length < 2048 / Unsafe.SizeOf<T>())
#pragma warning disable 8500 // sizeof of managed types
if (length < 2048 / sizeof(T))
#pragma warning restore 8500
{
return new T[length];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,10 @@ ptr is string ||

// Compat note: CLR wouldn't bother with a range check. If someone does this,
// they're likely taking dependency on some CLR implementation detail quirk.
if (checked(ofs + Unsafe.SizeOf<T>()) > size)
#pragma warning disable 8500 // sizeof of managed types
if (checked(ofs + sizeof(T)) > size)
throw new ArgumentOutOfRangeException(nameof(ofs));
#pragma warning restore 8500

IntPtr nativeBytes = AllocCoTaskMem(size);
NativeMemory.Clear((void*)nativeBytes, (nuint)size);
Expand Down Expand Up @@ -384,8 +386,10 @@ ptr is string ||

// Compat note: CLR wouldn't bother with a range check. If someone does this,
// they're likely taking dependency on some CLR implementation detail quirk.
if (checked(ofs + Unsafe.SizeOf<T>()) > size)
#pragma warning disable 8500 // sizeof of managed types
if (checked(ofs + sizeof(T)) > size)
throw new ArgumentOutOfRangeException(nameof(ofs));
#pragma warning restore 8500

IntPtr nativeBytes = AllocCoTaskMem(size);
NativeMemory.Clear((void*)nativeBytes, (nuint)size);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ public static MethodIL EmitIL(MethodDesc method)
{
case "AsPointer":
return new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldarg_0, (byte)ILOpcode.conv_u, (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null);
case "SizeOf":
return EmitSizeOf(method);
case "As":
case "AsRef":
return new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldarg_0, (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null);
Expand Down Expand Up @@ -98,19 +96,6 @@ public static MethodIL EmitIL(MethodDesc method)
return null;
}

private static MethodIL EmitSizeOf(MethodDesc method)
{
Debug.Assert(method.Signature.IsStatic && method.Signature.Length == 0);

TypeSystemContext context = method.Context;

ILEmitter emit = new ILEmitter();
ILCodeStream codeStream = emit.NewCodeStream();
codeStream.Emit(ILOpcode.sizeof_, emit.NewToken(context.GetSignatureVariable(0, method: true)));
codeStream.Emit(ILOpcode.ret);
return emit.Link(method);
}

private static MethodIL EmitAdd(MethodDesc method)
{
Debug.Assert(method.Signature.IsStatic && method.Signature.Length == 2);
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,6 @@ DEFINE_METHOD(UNSAFE, BYREF_IS_NULL, IsNullRef, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_NULLREF, NullRef, NoSig)
DEFINE_METHOD(UNSAFE, AS_REF_IN, AsRef, GM_RefT_RetRefT)
DEFINE_METHOD(UNSAFE, AS_REF_POINTER, AsRef, GM_VoidPtr_RetRefT)
DEFINE_METHOD(UNSAFE, SIZEOF, SizeOf, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_AS, As, GM_RefTFrom_RetRefTTo)
DEFINE_METHOD(UNSAFE, OBJECT_AS, As, GM_Obj_RetT)
DEFINE_METHOD(UNSAFE, BYREF_ADD, Add, GM_RefT_Int_RetRefT)
Expand Down
18 changes: 0 additions & 18 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6789,24 +6789,6 @@ bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn,

return true;
}
else if (tk == CoreLibBinder::GetMethod(METHOD__UNSAFE__SIZEOF)->GetMemberDef())
{
_ASSERTE(ftn->HasMethodInstantiation());
Instantiation inst = ftn->GetMethodInstantiation();

_ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
mdToken tokGenericArg = FindGenericMethodArgTypeSpec(CoreLibBinder::GetModule()->GetMDImport());

static const BYTE ilcode[] =
{
CEE_PREFIX1, (CEE_SIZEOF & 0xFF), (BYTE)(tokGenericArg), (BYTE)(tokGenericArg >> 8), (BYTE)(tokGenericArg >> 16), (BYTE)(tokGenericArg >> 24),
CEE_RET
};

setILIntrinsicMethodInfo(methInfo,const_cast<BYTE*>(ilcode),sizeof(ilcode), 1);

return true;
}
else if (tk == CoreLibBinder::GetMethod(METHOD__UNSAFE__BYREF_AS)->GetMemberDef() ||
tk == CoreLibBinder::GetMethod(METHOD__UNSAFE__OBJECT_AS)->GetMemberDef() ||
tk == CoreLibBinder::GetMethod(METHOD__UNSAFE__AS_REF_POINTER)->GetMemberDef() ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,9 @@ private static unsafe void SetEventData<T>(ref EventData eventData, ref T value,
else
{
eventData.DataPointer = (IntPtr)Unsafe.AsPointer(ref value);
eventData.Size = Unsafe.SizeOf<T>();
#pragma warning disable 8500 // sizeof of managed types
eventData.Size = sizeof(T);
#pragma warning restore 8500
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ internal sealed partial class ArrayMemoryPool<T> : MemoryPool<T>
{
public sealed override int MaxBufferSize => Array.MaxLength;

public sealed override IMemoryOwner<T> Rent(int minimumBufferSize = -1)
public sealed override unsafe IMemoryOwner<T> Rent(int minimumBufferSize = -1)
{
#pragma warning disable 8500 // sizeof of managed types
if (minimumBufferSize == -1)
minimumBufferSize = 1 + (4095 / Unsafe.SizeOf<T>());
minimumBufferSize = 1 + (4095 / sizeof(T));
else if (((uint)minimumBufferSize) > Array.MaxLength)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize);
#pragma warning restore 8500

return new ArrayMemoryPoolBuffer(minimumBufferSize);
}
Expand Down
22 changes: 12 additions & 10 deletions src/libraries/System.Private.CoreLib/src/System/Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

#pragma warning disable 8500 // sizeof of managed types

namespace System
{
[Serializable]
Expand Down Expand Up @@ -1308,7 +1310,7 @@ public static int IndexOf<T>(T[] array, T value, int startIndex)
return IndexOf(array, value, startIndex, array.Length - startIndex);
}

public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
public static unsafe int IndexOf<T>(T[] array, T value, int startIndex, int count)
{
if (array == null)
{
Expand All @@ -1327,31 +1329,31 @@ public static int IndexOf<T>(T[] array, T value, int startIndex, int count)

if (RuntimeHelpers.IsBitwiseEquatable<T>())
{
if (Unsafe.SizeOf<T>() == sizeof(byte))
if (sizeof(T) == sizeof(byte))
{
int result = SpanHelpers.IndexOfValueType(
ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<byte[]>(array)), startIndex),
Unsafe.As<T, byte>(ref value),
count);
return (result >= 0 ? startIndex : 0) + result;
}
else if (Unsafe.SizeOf<T>() == sizeof(short))
else if (sizeof(T) == sizeof(short))
{
int result = SpanHelpers.IndexOfValueType(
ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<short[]>(array)), startIndex),
Unsafe.As<T, short>(ref value),
count);
return (result >= 0 ? startIndex : 0) + result;
}
else if (Unsafe.SizeOf<T>() == sizeof(int))
else if (sizeof(T) == sizeof(int))
{
int result = SpanHelpers.IndexOfValueType(
ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<int[]>(array)), startIndex),
Unsafe.As<T, int>(ref value),
count);
return (result >= 0 ? startIndex : 0) + result;
}
else if (Unsafe.SizeOf<T>() == sizeof(long))
else if (sizeof(T) == sizeof(long))
{
int result = SpanHelpers.IndexOfValueType(
ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<long[]>(array)), startIndex),
Expand Down Expand Up @@ -1534,7 +1536,7 @@ public static int LastIndexOf<T>(T[] array, T value, int startIndex)
return LastIndexOf(array, value, startIndex, (array.Length == 0) ? 0 : (startIndex + 1));
}

public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count)
public static unsafe int LastIndexOf<T>(T[] array, T value, int startIndex, int count)
{
if (array == null)
{
Expand Down Expand Up @@ -1574,7 +1576,7 @@ public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count)

if (RuntimeHelpers.IsBitwiseEquatable<T>())
{
if (Unsafe.SizeOf<T>() == sizeof(byte))
if (sizeof(T) == sizeof(byte))
{
int endIndex = startIndex - count + 1;
int result = SpanHelpers.LastIndexOfValueType(
Expand All @@ -1584,7 +1586,7 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<byte[]>(array))

return (result >= 0 ? endIndex : 0) + result;
}
else if (Unsafe.SizeOf<T>() == sizeof(short))
else if (sizeof(T) == sizeof(short))
{
int endIndex = startIndex - count + 1;
int result = SpanHelpers.LastIndexOfValueType(
Expand All @@ -1594,7 +1596,7 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<short[]>(array)

return (result >= 0 ? endIndex : 0) + result;
}
else if (Unsafe.SizeOf<T>() == sizeof(int))
else if (sizeof(T) == sizeof(int))
{
int endIndex = startIndex - count + 1;
int result = SpanHelpers.LastIndexOfValueType(
Expand All @@ -1604,7 +1606,7 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As<int[]>(array)),

return (result >= 0 ? endIndex : 0) + result;
}
else if (Unsafe.SizeOf<T>() == sizeof(long))
else if (sizeof(T) == sizeof(long))
{
int endIndex = startIndex - count + 1;
int result = SpanHelpers.LastIndexOfValueType(
Expand Down
8 changes: 5 additions & 3 deletions src/libraries/System.Private.CoreLib/src/System/Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,24 +348,26 @@ internal static unsafe void _ZeroMemory(ref byte b, nuint byteLength)
#if !MONO // Mono BulkMoveWithWriteBarrier is in terms of elements (not bytes) and takes a type handle.

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Memmove<T>(ref T destination, ref T source, nuint elementCount)
internal static unsafe void Memmove<T>(ref T destination, ref T source, nuint elementCount)
{
#pragma warning disable 8500 // sizeof of managed types
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
// Blittable memmove
Memmove(
ref Unsafe.As<T, byte>(ref destination),
ref Unsafe.As<T, byte>(ref source),
elementCount * (nuint)Unsafe.SizeOf<T>());
elementCount * (nuint)sizeof(T));
}
else
{
// Non-blittable memmove
BulkMoveWithWriteBarrier(
ref Unsafe.As<T, byte>(ref destination),
ref Unsafe.As<T, byte>(ref source),
elementCount * (nuint)Unsafe.SizeOf<T>());
elementCount * (nuint)sizeof(T));
}
#pragma warning restore 8500
}

// The maximum block size to for __BulkMoveWithWriteBarrier FCall. This is required to avoid GC starvation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,13 +459,18 @@ public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure press
{
trimCount++;
}
if (Unsafe.SizeOf<T>() > StackModerateTypeSize)
unsafe
{
trimCount++;
}
if (Unsafe.SizeOf<T>() > StackLargeTypeSize)
{
trimCount++;
#pragma warning disable 8500 // sizeof of managed types
if (sizeof(T) > StackModerateTypeSize)
{
trimCount++;
}
if (sizeof(T) > StackLargeTypeSize)
{
trimCount++;
}
#pragma warning restore 8500
}
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ private static void IntroSort(Span<T> keys, int depthLimit)
}
}

private static int PickPivotAndPartition(Span<T> keys)
private static unsafe int PickPivotAndPartition(Span<T> keys)
{
Debug.Assert(keys.Length >= Array.IntrosortSizeThreshold);

Expand Down Expand Up @@ -494,7 +494,9 @@ private static int PickPivotAndPartition(Span<T> keys)
{
Swap(ref leftRef, ref nextToLastRef);
}
return (int)((nint)Unsafe.ByteOffset(ref zeroRef, ref leftRef) / Unsafe.SizeOf<T>());
#pragma warning disable 8500 // sizeof of managed types
return (int)((nint)Unsafe.ByteOffset(ref zeroRef, ref leftRef) / sizeof(T));
#pragma warning restore 8500
}

private static void HeapSort(Span<T> keys)
Expand Down
Loading