From: Yoh Deadfall Date: Fri, 7 Aug 2020 22:18:28 +0000 (+0300) Subject: Reduced code size and optimized name key creation for JSON properties and parameters... X-Git-Tag: submit/tizen/20210909.063632~6139 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=83ee84a7d62af9beac1999092c75c3a09d0d887d;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Reduced code size and optimized name key creation for JSON properties and parameters (#40136) --- diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs index 7b01b16..0de7ed3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs @@ -446,84 +446,47 @@ namespace System.Text.Json /// // AggressiveInlining used since this method is only called from two locations and is on a hot path. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong GetKey(ReadOnlySpan propertyName) + public static ulong GetKey(ReadOnlySpan name) { - const int BitsInByte = 8; ulong key; - int length = propertyName.Length; + + ref byte reference = ref MemoryMarshal.GetReference(name); + int length = name.Length; if (length > 7) { - key = MemoryMarshal.Read(propertyName) - & 0x00FFFFFFFFFFFFFF - // Include the length with a max of 0xFF. - | ((ulong)Math.Min(length, 0xFF)) << (7 * BitsInByte); - } - else if (length > 3) - { - key = MemoryMarshal.Read(propertyName); - - if (length == 7) - { - key |= (ulong)propertyName[6] << (6 * BitsInByte) - | (ulong)propertyName[5] << (5 * BitsInByte) - | (ulong)propertyName[4] << (4 * BitsInByte) - | (ulong)7 << (7 * BitsInByte); - } - else if (length == 6) - { - key |= (ulong)propertyName[5] << (5 * BitsInByte) - | (ulong)propertyName[4] << (4 * BitsInByte) - | (ulong)6 << (7 * BitsInByte); - } - else if (length == 5) - { - key |= (ulong)propertyName[4] << (4 * BitsInByte) - | (ulong)5 << (7 * BitsInByte); - } - else - { - key |= (ulong)4 << (7 * BitsInByte); - } + key = Unsafe.ReadUnaligned(ref reference) & 0x00ffffffffffffffL; + key |= (ulong)Math.Min(length, 0xff) << 56; } - else if (length > 1) + else { - key = MemoryMarshal.Read(propertyName); + key = + length > 5 ? Unsafe.ReadUnaligned(ref reference) | (ulong)Unsafe.ReadUnaligned(ref Unsafe.Add(ref reference, 4)) << 32 : + length > 3 ? Unsafe.ReadUnaligned(ref reference) : + length > 1 ? Unsafe.ReadUnaligned(ref reference) : 0UL; + key |= (ulong)length << 56; - if (length == 3) - { - key |= (ulong)propertyName[2] << (2 * BitsInByte) - | (ulong)3 << (7 * BitsInByte); - } - else + if ((length & 1) != 0) { - key |= (ulong)2 << (7 * BitsInByte); + var offset = length - 1; + key |= (ulong)Unsafe.Add(ref reference, offset) << (offset * 8); } } - else if (length == 1) - { - key = propertyName[0] - | (ulong)1 << (7 * BitsInByte); - } - else - { - // An empty name is valid. - key = 0; - } // Verify key contains the embedded bytes as expected. + const int BitsInByte = 8; Debug.Assert( // Verify embedded property name. - (length < 1 || propertyName[0] == ((key & ((ulong)0xFF << BitsInByte * 0)) >> BitsInByte * 0)) && - (length < 2 || propertyName[1] == ((key & ((ulong)0xFF << BitsInByte * 1)) >> BitsInByte * 1)) && - (length < 3 || propertyName[2] == ((key & ((ulong)0xFF << BitsInByte * 2)) >> BitsInByte * 2)) && - (length < 4 || propertyName[3] == ((key & ((ulong)0xFF << BitsInByte * 3)) >> BitsInByte * 3)) && - (length < 5 || propertyName[4] == ((key & ((ulong)0xFF << BitsInByte * 4)) >> BitsInByte * 4)) && - (length < 6 || propertyName[5] == ((key & ((ulong)0xFF << BitsInByte * 5)) >> BitsInByte * 5)) && - (length < 7 || propertyName[6] == ((key & ((ulong)0xFF << BitsInByte * 6)) >> BitsInByte * 6)) && + (name.Length < 1 || name[0] == ((key & ((ulong)0xFF << BitsInByte * 0)) >> BitsInByte * 0)) && + (name.Length < 2 || name[1] == ((key & ((ulong)0xFF << BitsInByte * 1)) >> BitsInByte * 1)) && + (name.Length < 3 || name[2] == ((key & ((ulong)0xFF << BitsInByte * 2)) >> BitsInByte * 2)) && + (name.Length < 4 || name[3] == ((key & ((ulong)0xFF << BitsInByte * 3)) >> BitsInByte * 3)) && + (name.Length < 5 || name[4] == ((key & ((ulong)0xFF << BitsInByte * 4)) >> BitsInByte * 4)) && + (name.Length < 6 || name[5] == ((key & ((ulong)0xFF << BitsInByte * 5)) >> BitsInByte * 5)) && + (name.Length < 7 || name[6] == ((key & ((ulong)0xFF << BitsInByte * 6)) >> BitsInByte * 6)) && // Verify embedded length. - (length >= 0xFF || (key & ((ulong)0xFF << BitsInByte * 7)) >> BitsInByte * 7 == (ulong)length) && - (length < 0xFF || (key & ((ulong)0xFF << BitsInByte * 7)) >> BitsInByte * 7 == 0xFF)); + (name.Length >= 0xFF || (key & ((ulong)0xFF << BitsInByte * 7)) >> BitsInByte * 7 == (ulong)name.Length) && + (name.Length < 0xFF || (key & ((ulong)0xFF << BitsInByte * 7)) >> BitsInByte * 7 == 0xFF)); return key; }