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

Remove StringSpanHelpers and start using MemoryExtensions#16718

Merged
ahsonkhan merged 3 commits intodotnet:masterfrom
ahsonkhan:SpanStringCleanup
Mar 4, 2018
Merged

Remove StringSpanHelpers and start using MemoryExtensions#16718
ahsonkhan merged 3 commits intodotnet:masterfrom
ahsonkhan:SpanStringCleanup

Conversation

@ahsonkhan
Copy link

cc @stephentoub, @jkotas, @tarekgh, @benaadams

Ignore the change to src/jit/hwintrinsiclistxarch.h (it's from #16715)

@ahsonkhan
Copy link
Author

@dotnet-bot test Windows_NT arm Cross Checked corefx_baseline Build and Test
@dotnet-bot test Windows_NT x64_arm64_altjit Checked corefx_baseline
@dotnet-bot test Ubuntu x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x86_arm_altjit Checked corefx_baseline
@dotnet-bot test Windows_NT x86 Checked corefx_baseline

@ahsonkhan
Copy link
Author

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@jcagme
Copy link

jcagme commented Mar 2, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please

2 similar comments
@jcagme
Copy link

jcagme commented Mar 2, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please

@jcagme
Copy link

jcagme commented Mar 2, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please


// TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
internal virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
internal virtual int CompareOptionNone(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why take take an options and force it to be None if it's not going to be used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to pass the option to CompareString which passes it to the interop call.

Copy link
Author

@ahsonkhan ahsonkhan Mar 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I just realized what you meant. Lol.

We can simply do the following:

        internal virtual int CompareOptionNone(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
        {
            return _invariantMode ?
                string.CompareOrdinal(string1, string2) :
                CompareString(string1, string2, CompareOptions.None);
        }

return CompareString(string1, string2, options);
internal virtual int CompareOptionIgnoreCase(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
{
Debug.Assert(options == CompareOptions.IgnoreCase);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question for IgnoreCase... why aren't all of these just calling CompareString?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I make private unsafe int CompareString(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options) internal and call it directly?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind. Ignore my comment.

@jcagme
Copy link

jcagme commented Mar 2, 2018

Trying MSIT fix
@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please

// Find the end of this hex number (since it is not fixed length)
numStart = 3;
numLen = guidString.IndexOf(',', numStart) - numStart;
numLen = guidString.Slice(numStart).IndexOf(',') - numStart;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you runs our tests, and does this pass? Putting in the slice will change the resulting value as compared to passing in a start index.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment for all of these.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran the corefx System.Runtime tests locally. I didn't run the coreclr tests.

I will fix the bug and run the coreclr tests.

Copy link
Member

@stephentoub stephentoub Mar 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually meant the corefx tests. If we don't have a test that catches this, we should. This is wrong, right? Consider if numStart is 3 and the ',' is found at 4. Previously IndexOf(',',numStart) would return 4, and then we'd subtract 3 to get 1. Now IndexOf(',') will return 1, and then we'll subtract 3 to get -2.

Copy link
Author

@ahsonkhan ahsonkhan Mar 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is incorrect. We need to remove the - numStart

Copy link
Author

@ahsonkhan ahsonkhan Mar 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have these tests that, theoretically, should call into TryParseGuidWithHexPrefix. I will re-run the tests locally to see if they fail.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the tests catch this bug and do fail. I must not have re-built coreclr successfully with my changes earlier (probably due to the issue with HW_Flag_BaseTypeFromFirstArg).

Span<char> result = new char[i + 1];
result[i] = ch;
Value.Slice(0, i).CopyTo(result);
Value = result.AsReadOnlySpan();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any tests that hit this and the below removal paths? It'd be good to make sure they're covered.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check and add if needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// We musn't have any separators after build.
int buildEnd = -1;
int minorEnd = input.IndexOf('.', majorEnd + 1);
int minorEnd = input.Slice(majorEnd + 1).IndexOf('.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As with the other cases where slicing was added, I don't think this and the below cases do the right thing.


public bool StartsWith(char value) => Length != 0 && _firstChar == value;

public static void CheckStringComparison(StringComparison comparisonType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Will fix.

// Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
if ((uint)(comparisonType - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
{
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use ThrowHelper?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use ThrowHelper anywhere in this file. In what scenario would it help?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ThrowHelper outside generics (where its codegen size); it helps with inlining and the size when inlined.

So

((uint)(comparisonType - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))

will probably easily inline

but add new, throw, nameof, SR.NotSupported_StringComparison and it probably won't

Whereas ThrowHelper.ThrowArgumentException(ExceptionResource.NotSupported_StringComparison) is one int constant register load and a call with no post cleanup (as it only throws).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. So, it will help inline CheckStringComparison, mainly for when it won't end up throwing (which is the most common scenario).

@jcagme
Copy link

jcagme commented Mar 2, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please

1 similar comment
@jcagme
Copy link

jcagme commented Mar 3, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please

@ahsonkhan
Copy link
Author

OSX - https://github.com/dotnet/core-eng/issues/2808
Tizen:

qemu: Unsupported syscall: 389

Any other feedback before this gets merged?

@ahsonkhan
Copy link
Author

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@ahsonkhan ahsonkhan merged commit 7ac6d5c into dotnet:master Mar 4, 2018
@ahsonkhan ahsonkhan deleted the SpanStringCleanup branch March 4, 2018 01:48
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants