From 5dd44a2100259ad8be0e92a15b5416260b199ac6 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 22 Mar 2023 00:01:50 -0400 Subject: [PATCH] Remove now unnecessary IsKnownConstant special-casing in interpolated string handlers Now that the JIT will unroll memcpys, we're better off just letting it do its thing. --- .../src/System/MemoryExtensions.cs | 65 +--------------- .../DefaultInterpolatedStringHandler.cs | 77 +------------------ 2 files changed, 7 insertions(+), 135 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index bd3880987dfa4..7db3907fba281 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -4040,65 +4040,6 @@ public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, /// true if the value could be formatted to the span; otherwise, false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool AppendLiteral(string value) - { - if (RuntimeHelpers.IsKnownConstant(value)) - { - // See comment on inlining and special-casing in DefaultInterpolatedStringHandler.AppendLiteral. - - if (value.Length == 1) - { - Span destination = _destination; - int pos = _pos; - if ((uint)pos < (uint)destination.Length) - { - destination[pos] = value[0]; - _pos = pos + 1; - return true; - } - - return Fail(); - } - - if (value.Length == 2) - { - Span destination = _destination; - int pos = _pos; - if ((uint)pos < destination.Length - 1) - { - Unsafe.WriteUnaligned( - ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(destination), pos)), - Unsafe.ReadUnaligned(ref Unsafe.As(ref value.GetRawStringData()))); - _pos = pos + 2; - return true; - } - - return Fail(); - } - - if (value.Length == 4) - { - Span destination = _destination; - int pos = _pos; - if ((uint)pos < destination.Length - 3) - { - Unsafe.WriteUnaligned( - ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(destination), pos)), - Unsafe.ReadUnaligned(ref Unsafe.As(ref value.GetRawStringData()))); - _pos = pos + 4; - return true; - } - - return Fail(); - } - } - - return AppendStringDirect(value); - } - - /// Writes the specified string to the handler. - /// The string to write. - /// true if the value could be appended to the span; otherwise, false. - private bool AppendStringDirect(string value) { if (value.TryCopyTo(_destination.Slice(_pos))) { @@ -4170,7 +4111,7 @@ public bool AppendFormatted(T value) s = value?.ToString(); } - return s is null || AppendStringDirect(s); + return s is null || AppendLiteral(s); } /// Writes the specified value to the handler. @@ -4226,7 +4167,7 @@ public bool AppendFormatted(T value, string? format) s = value?.ToString(); } - return s is null || AppendStringDirect(s); + return s is null || AppendLiteral(s); } /// Writes the specified value to the handler. @@ -4390,7 +4331,7 @@ private bool AppendCustomFormatter(T value, string? format) if (formatter is not null && formatter.Format(format, value, _provider) is string customFormatted) { - return AppendStringDirect(customFormatted); + return AppendLiteral(customFormatted); } return true; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs index 79e0afeb1cfe9..1d47cfb2b4870 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs @@ -133,75 +133,6 @@ internal void Clear() /// The string to write. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AppendLiteral(string value) - { - if (RuntimeHelpers.IsKnownConstant(value)) - { - // AppendLiteral is expected to be called by compiler-generated code with a literal string. - // By inlining it, the method body is exposed to the constant length of that literal, allowing the JIT to - // prune away the irrelevant cases. This effectively enables multiple implementations of AppendLiteral, - // special-cased on and optimized for the literal's length. We special-case lengths 1 and 2 because - // they're very common, e.g. - // 1: ' ', '.', '-', '\t', etc. - // 2: ", ", "0x", "=>", ": ", etc. - // and length 4 because it can similarly be done with a single read/write. - - if (value.Length == 1) - { - int pos = _pos; - Span chars = _chars; - if ((uint)pos < (uint)chars.Length) - { - chars[pos] = value[0]; - _pos = pos + 1; - } - else - { - GrowThenCopyString(value); - } - return; - } - - if (value.Length == 2) - { - int pos = _pos; - if ((uint)pos < _chars.Length - 1) - { - Unsafe.WriteUnaligned( - ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(_chars), pos)), - Unsafe.ReadUnaligned(ref Unsafe.As(ref value.GetRawStringData()))); - _pos = pos + 2; - } - else - { - GrowThenCopyString(value); - } - return; - } - - if (value.Length == 4) - { - int pos = _pos; - if ((uint)pos < _chars.Length - 3) - { - Unsafe.WriteUnaligned( - ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(_chars), pos)), - Unsafe.ReadUnaligned(ref Unsafe.As(ref value.GetRawStringData()))); - _pos = pos + 4; - } - else - { - GrowThenCopyString(value); - } - return; - } - } - - AppendStringDirect(value); - } - - /// Writes the specified string to the handler. - /// The string to write. - private void AppendStringDirect(string value) { if (value.TryCopyTo(_chars.Slice(_pos))) { @@ -350,7 +281,7 @@ public void AppendFormatted(T value) if (s is not null) { - AppendStringDirect(s); + AppendLiteral(s); } } @@ -412,7 +343,7 @@ public void AppendFormatted(T value, string? format) if (s is not null) { - AppendStringDirect(s); + AppendLiteral(s); } } @@ -596,7 +527,7 @@ private void AppendCustomFormatter(T value, string? format) if (formatter is not null && formatter.Format(format, value, _provider) is string customFormatted) { - AppendStringDirect(customFormatted); + AppendLiteral(customFormatted); } } @@ -646,7 +577,7 @@ private void EnsureCapacityForAdditionalChars(int additionalChars) } } - /// Fallback for fast path in when there's not enough space in the destination. + /// Fallback for fast path in when there's not enough space in the destination. /// The string to write. [MethodImpl(MethodImplOptions.NoInlining)] private void GrowThenCopyString(string value)