From f1bc65a6df27f37beff19ae9d7369cb55dc60dd2 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Fri, 14 Feb 2020 06:30:06 +0000 Subject: [PATCH] Shrink Dictionary asm by moving non-generic enumerator out --- .../System.Private.CoreLib.Shared.projitems | 1 + .../System/Collections/Generic/Dictionary.cs | 66 ++----------------- .../Generic/DictionaryEnumerator.cs | 41 ++++++++++++ .../Collections/Generic/KeyValuePair.cs | 6 +- 4 files changed, 54 insertions(+), 60 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Collections/Generic/DictionaryEnumerator.cs diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 4c42870c7db34f..10acb9bdad2c74 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -129,6 +129,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs index 0ea5ce6c78ebbc..4ae73ba63bcce0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs @@ -302,10 +302,10 @@ private void CopyTo(KeyValuePair[] array, int index) } public Enumerator GetEnumerator() - => new Enumerator(this, Enumerator.KeyValuePair); + => new Enumerator(this); IEnumerator> IEnumerable>.GetEnumerator() - => new Enumerator(this, Enumerator.KeyValuePair); + => new Enumerator(this); public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { @@ -976,7 +976,7 @@ void ICollection.CopyTo(Array array, int index) } IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(this, Enumerator.KeyValuePair); + => new Enumerator(this); /// /// Ensures that the dictionary can hold up to 'capacity' entries without any further expansion of its backing storage @@ -1152,7 +1152,7 @@ bool IDictionary.Contains(object key) } IDictionaryEnumerator IDictionary.GetEnumerator() - => new Enumerator(this, Enumerator.DictEntry); + => new DictionaryEnumerator(this); void IDictionary.Remove(object key) { @@ -1173,24 +1173,18 @@ private ref int GetBucket(uint hashCode) #endif } - public struct Enumerator : IEnumerator>, - IDictionaryEnumerator + public struct Enumerator : IEnumerator> { private readonly Dictionary _dictionary; private readonly int _version; private int _index; private KeyValuePair _current; - private readonly int _getEnumeratorRetType; // What should Enumerator.Current return? - internal const int DictEntry = 1; - internal const int KeyValuePair = 2; - - internal Enumerator(Dictionary dictionary, int getEnumeratorRetType) + internal Enumerator(Dictionary dictionary) { _dictionary = dictionary; _version = dictionary._version; _index = 0; - _getEnumeratorRetType = getEnumeratorRetType; _current = default; } @@ -1234,14 +1228,7 @@ public void Dispose() ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } - if (_getEnumeratorRetType == DictEntry) - { - return new DictionaryEntry(_current.Key, _current.Value); - } - else - { - return new KeyValuePair(_current.Key, _current.Value); - } + return _current; } } @@ -1255,45 +1242,6 @@ void IEnumerator.Reset() _index = 0; _current = default; } - - DictionaryEntry IDictionaryEnumerator.Entry - { - get - { - if (_index == 0 || (_index == _dictionary._count + 1)) - { - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); - } - - return new DictionaryEntry(_current.Key, _current.Value); - } - } - - object IDictionaryEnumerator.Key - { - get - { - if (_index == 0 || (_index == _dictionary._count + 1)) - { - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); - } - - return _current.Key; - } - } - - object? IDictionaryEnumerator.Value - { - get - { - if (_index == 0 || (_index == _dictionary._count + 1)) - { - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); - } - - return _current.Value; - } - } } [DebuggerTypeProxy(typeof(DictionaryKeyCollectionDebugView<,>))] diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/DictionaryEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/DictionaryEnumerator.cs new file mode 100644 index 00000000000000..5192a2aacc8320 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/DictionaryEnumerator.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Collections.Generic +{ + internal interface IKeyValue + { + public object? Key { get; } + public object? Value { get; } + } + + internal class DictionaryEnumerator : IDictionaryEnumerator + { + private readonly IEnumerator _enumerator; + private IKeyValue? _current; + + public DictionaryEnumerator(IEnumerable enumerable) + { + _enumerator = enumerable.GetEnumerator(); + _current = null; + } + + public object Key => _current?.Key!; + + public object? Value => _current?.Value; + + public DictionaryEntry Entry => new DictionaryEntry(_current?.Key!, _current?.Value); + + public object? Current => _current; + + public bool MoveNext() + { + bool result = _enumerator.MoveNext(); + _current = (IKeyValue)_enumerator.Current!; + return result; + } + + public void Reset() => _enumerator.Reset(); + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs index f3c5462ee73a99..f5817e79212ce3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs @@ -49,7 +49,7 @@ internal static string PairToString(object? key, object? value) // and IReadOnlyDictionary. [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public readonly struct KeyValuePair + public readonly struct KeyValuePair : IKeyValue { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly TKey key; // Do not rename (binary serialization) @@ -66,6 +66,10 @@ public KeyValuePair(TKey key, TValue value) public TValue Value => value; + object? IKeyValue.Key => key; + + object? IKeyValue.Value => value; + public override string ToString() { return KeyValuePair.PairToString(Key, Value);