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

Consume Span moves - #26467

Merged
ianhays merged 2 commits into
dotnet:masterfrom
ianhays:memory_moves
Jan 29, 2018
Merged

Consume Span moves#26467
ianhays merged 2 commits into
dotnet:masterfrom
ianhays:memory_moves

Conversation

@ianhays

@ianhays ianhays commented Jan 20, 2018

Copy link
Copy Markdown
Contributor

Depends on dotnet/coreclr#15941

resolves #26368
resolves #24854
resolves #26295
resolves #26139

@ianhays ianhays added this to the 2.1.0 milestone Jan 20, 2018
@ianhays ianhays self-assigned this Jan 20, 2018
@ianhays
ianhays requested a review from ahsonkhan January 20, 2018 00:13
<!-- disable warnings about obsolete APIs -->
<NoWarn>$(NoWarn);0809</NoWarn>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netcoreapp' Or '$(TargetGroup)' == 'uap'">true</IsPartialFacadeAssembly>
<DefineConstants Condition="'$(IsPartialFacadeAssembly)' != 'true'">$(DefineConstants);netstandard;FEATURE_PORTABLE_SPAN</DefineConstants>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we remove the netstandard constant?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure can!

{
[Fact]
public static void DangerousCreate1()
public static void CreateReadOnlySpan1()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: remove the 1 suffix from the test name.

{
[Fact]
public static void DangerousCreate1()
public static void CreateSpan1()

@ahsonkhan ahsonkhan Jan 20, 2018

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Same here. Not sure why it was DangerousCreate1 to begin with.

Also elsewhere.

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ProjectGuid>{15DB0DCC-68B4-4CFB-8BD2-F26BCCAF5A3F}</ProjectGuid>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netcoreapp' OR '$(TargetGroup)' == 'uap'">true</IsPartialFacadeAssembly>
<DefineConstants Condition="'$(IsPartialFacadeAssembly)' != 'true'">$(DefineConstants);netstandard;FEATURE_PORTABLE_SPAN</DefineConstants>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These constants seem unnecessary (not used).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. I added them to keep the new tests in a single file and used IFDEFS but decided that was cumbersome so broke them up into group-specific files included based on IsPartialFacadeAssembly.

I'll remove the DefineConstants.

@ahsonkhan ahsonkhan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We need to add the ToString() methods to the System.Memory ref as well (for Span/ReadOnlySpan).

public int Length { get { throw null; } }
public void CopyTo(System.Span<T> destination) { }
[System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))]
public static System.ReadOnlySpan<T> DangerousCreate(object obj, ref T objectData, int length) { throw null; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All these changes need to be made to the System.Runtime ref as well.

@ianhays

ianhays commented Jan 24, 2018

Copy link
Copy Markdown
Contributor Author

@ahsonkhan thanks for the feedback! I addressed all of it.

@ianhays

ianhays commented Jan 24, 2018

Copy link
Copy Markdown
Contributor Author

@ianhays

ianhays commented Jan 26, 2018

Copy link
Copy Markdown
Contributor Author

Pinging @KrzysztofCwalina @GrabYourPitchforks @ahsonkhan @stephentoub for final feedback.

if (SpanHelpers.IsReferenceOrContainsReferences<TTo>())
ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TTo));

int newLength = checked((int)((long)source.Length * Unsafe.SizeOf<TFrom>() / Unsafe.SizeOf<TTo>()));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we check that TTo's size is more than zero? i.e. what happens if I cast from span of bytes to a span of empty structs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Unsafe.SizeOf<TTo> returns a nonzero value for all types.

Added this test:

        struct EmptyStruct { }

        [Fact]
        public static void CastSpanToEmptyStruct()
        {
            Span<uint> span = new Span<uint>(new uint[] { 1 });
            Span<EmptyStruct> emptyspan = MemoryMarshal.Cast<uint, EmptyStruct>(span);
            Assert.Equal(1, Unsafe.SizeOf<EmptyStruct>());
            Assert.Equal(4, emptyspan.Length);
        }

<Compile Include="MemoryMarshal\AsMemory.cs" />
<Compile Include="MemoryMarshal\GetReference.cs" />
<Compile Include="MemoryMarshal\TryGetArray.cs" />
<Compile Include="MemoryMarshal\CastReadOnlySpan.cs" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: sort order as alphabetical

@ahsonkhan ahsonkhan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Otherwise, lgtm.

@AndyAyersMS

Copy link
Copy Markdown
Member

The checked multiply pattern in Cast generates some ugly code which can be avoided in many cases by doing some case analysis.

See notes over in dotnet/coreclr#15492.

If we're going to leave it as is, then I'd get rid of the aggressive inlining attribute.

- [Move Span.DangerousCreate to MemoryMarshal.CreateSpan](#26139)
- [Move ReadOnlySpan.DangerousCreate to MemoryMarshal.CreateReadOnlySpan](#26139)
- [Move Span.NonPortableCast to MemoryMarshal.Cast](#26368)
- [Move ReadOnlySpan.NonPortableCast to MemoryMarshal.Cast](#26368)
- [Add ToString override to Span and ReadOnlySpan](#26295)
- [Add ToEnumerable function to MemoryMarshal that takes a Memory](#24854)
@ahsonkhan

Copy link
Copy Markdown

@ianhays, can you please maintain the commit history during PR review? It makes it easier to view only the diffs between commits.

Comment thread src/System.Memory/src/System/Span.cs Outdated
/// Returns a <see cref="String"/> with the name of the type and the number of elements
/// </summary>
/// <returns>A <see cref="String"/> with the name of the type and the number of elements</returns>
public override string ToString() => $"System.Span[{Length}]";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should this be identical to the DebuggerDisplay string (i.e. should we include typeof(T).Name to ToString) - SpanDebuggerDisplay / ReadOnlySpanDebuggerDisplay?

Similarly, should we add the prefix "System.Span" to the DebuggerDisplay, with angle brackets around the type T?

For instance, I propose the following:

Span<int> span = new int[10];
string str = span.ToString(); //System.Span<int>[10]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure, that would be useful.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated with the new ToString/DebuggerDisplay string.

I'll post a PR to coreclr with the new strings to FastSpan along with the removal of the old NonPortableCast functions after this PR in corefx is merged.

@ianhays

ianhays commented Jan 29, 2018

Copy link
Copy Markdown
Contributor Author

can you please maintain the commit history during PR review? It makes it easier to view only the diffs between commits.

Apologies, I wasn't expecting any more feedback. That rebase was to remove the feedback commits pre-merge.

@ahsonkhan ahsonkhan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks good!

@ianhays
ianhays merged commit 540a99c into dotnet:master Jan 29, 2018
@ianhays

ianhays commented Jan 29, 2018

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback! merged.

picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Consume Span moves
- [Move Span.DangerousCreate to MemoryMarshal.CreateSpan](dotnet/corefx#26139)
- [Move ReadOnlySpan.DangerousCreate to MemoryMarshal.CreateReadOnlySpan](dotnet/corefx#26139)
- [Move Span.NonPortableCast to MemoryMarshal.Cast](dotnet/corefx#26368)
- [Move ReadOnlySpan.NonPortableCast to MemoryMarshal.Cast](dotnet/corefx#26368)
- [Add ToString override to Span and ReadOnlySpan](dotnet/corefx#26295)
- [Add ToEnumerable function to MemoryMarshal that takes a Memory](dotnet/corefx#24854)


Commit migrated from dotnet/corefx@540a99c
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

4 participants