Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Move NullRefs to Unsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams committed Oct 12, 2019
1 parent 559d375 commit 28fa945
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -387,5 +387,21 @@ public static IntPtr ByteOffset<T>(ref T origin, ref T target)
{
throw new PlatformNotSupportedException();
}

/// <summary>
/// Determines the byte offset from origin to target from the given references.
/// </summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe bool IsNullRef<T>(in T value)
=> Unsafe.AsPointer(ref Unsafe.AsRef(in value!)) == null ? true : false;

/// <summary>
/// Determines the byte offset from origin to target from the given references.
/// </summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe ref T NullRef<T>()
=> ref Unsafe.AsRef<T>(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Runtime.Serialization;
using System.Runtime.InteropServices;

using Internal.Runtime.CompilerServices;

namespace System.Collections.Generic
{
/// <summary>
Expand Down Expand Up @@ -171,7 +173,7 @@ public TValue this[TKey key]
get
{
ref TValue value = ref FindValueOrNull(key);
if (!RuntimeHelpers.IsNullRef(in value))
if (!Unsafe.IsNullRef(in value))
{
return value;
}
Expand All @@ -197,7 +199,7 @@ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyV
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
{
ref TValue value = ref FindValueOrNull(keyValuePair.Key);
if (!RuntimeHelpers.IsNullRef(in value) && EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value))
if (!Unsafe.IsNullRef(in value) && EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value))
{
return true;
}
Expand All @@ -207,7 +209,7 @@ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue>
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
{
ref TValue value = ref FindValueOrNull(keyValuePair.Key);
if (!RuntimeHelpers.IsNullRef(in value) && EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value))
if (!Unsafe.IsNullRef(in value) && EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value))
{
Remove(keyValuePair.Key);
return true;
Expand Down Expand Up @@ -235,7 +237,7 @@ public void Clear()
public bool ContainsKey(TKey key)
{
ref TValue value = ref FindValueOrNull(key);
return !RuntimeHelpers.IsNullRef(in value);
return !Unsafe.IsNullRef(in value);
}

public bool ContainsValue(TValue value)
Expand Down Expand Up @@ -339,7 +341,7 @@ private ref TValue FindValueOrNull(TKey key)
int[]? buckets = _buckets;
Entry[]? entries = _entries;
int collisionCount = 0;
ref TValue value = ref RuntimeHelpers.CreateNullRef<TValue>();
ref TValue value = ref Unsafe.NullRef<TValue>();
if (buckets != null)
{
Debug.Assert(entries != null, "expected entries to be != null");
Expand Down Expand Up @@ -869,7 +871,7 @@ public bool Remove(TKey key, [MaybeNullWhen(false)] out TValue value)
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
ref TValue entry = ref FindValueOrNull(key);
if (!RuntimeHelpers.IsNullRef(in entry))
if (!Unsafe.IsNullRef(in entry))
{
value = entry;
return true;
Expand Down Expand Up @@ -1037,7 +1039,7 @@ public void TrimExcess(int capacity)
if (IsCompatibleKey(key))
{
ref TValue value = ref FindValueOrNull((TKey)key);
if (!RuntimeHelpers.IsNullRef(in value))
if (!Unsafe.IsNullRef(in value))
{
return value;
}
Expand Down
2 changes: 1 addition & 1 deletion src/System.Private.CoreLib/shared/System/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public unsafe Span<T> Span
// in which case that's the dangerous operation performed by the dev, and we're just following
// suit here to make it work as best as possible.

ref T refToReturn = ref RuntimeHelpers.CreateNullRef<T>();
ref T refToReturn = ref Unsafe.NullRef<T>();
int lengthOfUnderlyingSpan = 0;

// Copy this field into a local so that it can't change out from under us mid-operation.
Expand Down
2 changes: 1 addition & 1 deletion src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public unsafe ReadOnlySpan<T> Span
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref T refToReturn = ref RuntimeHelpers.CreateNullRef<T>();
ref T refToReturn = ref Unsafe.NullRef<T>();
int lengthOfUnderlyingSpan = 0;

// Copy this field into a local so that it can't change out from under us mid-operation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public ref readonly T this[int index]
public ref readonly T GetPinnableReference()
{
// Ensure that the native code has just one forward branch that is predicted-not-taken.
ref T ret = ref RuntimeHelpers.CreateNullRef<T>();
ref T ret = ref Unsafe.NullRef<T>();
if (_length != 0) ret = ref _pointer.Value;
return ref ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,5 @@ public static void PrepareConstrainedRegions()
public static void PrepareConstrainedRegionsNoOP()
{
}

internal static unsafe bool IsNullRef<T>(in T value)
=> Unsafe.AsPointer(ref Unsafe.AsRef(in value!)) == null ? true : false;

internal static unsafe ref T CreateNullRef<T>()
=> ref Unsafe.AsRef<T>(null);
}
}
2 changes: 1 addition & 1 deletion src/System.Private.CoreLib/shared/System/Span.Fast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public ref T this[int index]
public unsafe ref T GetPinnableReference()
{
// Ensure that the native code has just one forward branch that is predicted-not-taken.
ref T ret = ref RuntimeHelpers.CreateNullRef<T>();
ref T ret = ref Unsafe.NullRef<T>();
if (_length != 0) ret = ref _pointer.Value;
return ref ret;
}
Expand Down

0 comments on commit 28fa945

Please sign in to comment.