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

Commit

Permalink
Split FindEntry default and custom
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams committed Sep 18, 2017
1 parent f8129a1 commit ed66712
Showing 1 changed file with 126 additions and 3 deletions.
129 changes: 126 additions & 3 deletions src/mscorlib/src/System/Collections/Generic/Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,31 +336,93 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ref Entry FindEntry(TKey key, out bool found)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}

IEqualityComparer<TKey> comparer = _customComparer;
if (comparer == null)
{
return ref FindEntryDefaultComparer(key, out found);
}
else
{
return ref FindEntryCustomComparer(key, comparer, out found);
}
}

private ref Entry FindEntryDefaultComparer(TKey key, out bool found)
{
Debug.Assert(key != null);

found = true;
int[] buckets = _buckets;
if (buckets != null)
{
int hashCode = KeyHashCode(key);
int hashCode;
if (default(TKey) == null)
{
hashCode = key?.GetHashCode() & 0x7FFFFFFF ?? 0;
}
else
{
hashCode = key.GetHashCode() & 0x7FFFFFFF;
}

Entry[] entries = _entries;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next)
{
ref Entry entry = ref entries[i];
if (entry.hashCode == hashCode && KeyEquals(entry.key, key))
if (entry.hashCode == hashCode)
{
if (default(TKey) == null && (entry.key?.Equals(key) ?? key == null))
{
return ref entry;
}
else if (StructKeyEquals(entry.key, key))
{
return ref entry;
}
}
}
}

found = false;
return ref NotFound;
}

private ref Entry FindEntryCustomComparer(TKey key, IEqualityComparer<TKey> comparer, out bool found)
{
Debug.Assert(key != null);

found = true;
int[] buckets = _buckets;
if (buckets != null)
{
int hashCode = comparer.GetHashCode(key);
Entry[] entries = _entries;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next)
{
ref Entry entry = ref entries[i];
if (entry.hashCode == hashCode && comparer.Equals(entry.key, key))
{
return ref entry;
}
}
}

found = false;
return ref s_nullEntry;
return ref NotFound;
}

private ref Entry NotFound
{
[MethodImpl(MethodImplOptions.NoInlining)]
get => ref s_nullEntry;
}

private int[] Initialize(int capacity)
Expand Down Expand Up @@ -671,6 +733,67 @@ public bool TryGetValue(TKey key, out TValue value)

public bool TryAdd(TKey key, TValue value) => TryInsert(key, value, InsertionBehavior.None);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool StructKeyEquals(TKey key0, TKey key1)
{
#if EQUALITYCOMPARER_INTRINSIC
return EqualityComparer<TKey>.Default.Equals(key0, key1);
#else
if (typeof(TKey) == typeof(byte))
{
return (byte)(object)key0 == (byte)(object)key1;
}
else if (typeof(TKey) == typeof(sbyte))
{
return (sbyte)(object)key0 == (sbyte)(object)key1;
}
else if (typeof(TKey) == typeof(ushort))
{
return (ushort)(object)key0 == (ushort)(object)key1;
}
else if (typeof(TKey) == typeof(short))
{
return (short)(object)key0 == (short)(object)key1;
}
else if (typeof(TKey) == typeof(char))
{
return (char)(object)key0 == (char)(object)key1;
}
else if (typeof(TKey) == typeof(uint))
{
return (uint)(object)key0 == (uint)(object)key1;
}
else if (typeof(TKey) == typeof(int))
{
return (int)(object)key0 == (int)(object)key1;
}
else if (typeof(TKey) == typeof(ulong))
{
return (ulong)(object)key0 == (ulong)(object)key1;
}
else if (typeof(TKey) == typeof(long))
{
return (long)(object)key0 == (long)(object)key1;
}
else if (typeof(TKey) == typeof(IntPtr))
{
return (IntPtr)(object)key0 == (IntPtr)(object)key1;
}
else if (typeof(TKey) == typeof(UIntPtr))
{
return (UIntPtr)(object)key0 == (UIntPtr)(object)key1;
}
else if (typeof(TKey) == typeof(Guid))
{
return (Guid)(object)key0 == (Guid)(object)key1;
}
else
{
return EqualityComparer<TKey>.Default.Equals(key0, key1);
}
#endif
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool KeyEquals(TKey key0, TKey key1)
{
Expand Down

0 comments on commit ed66712

Please sign in to comment.