Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop .NET Core 3.1 TFM #502

Merged
merged 3 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CommunityToolkit.HighPerformance/Buffers/MemoryOwner{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
using System.Runtime.InteropServices;
#endif
using CommunityToolkit.HighPerformance.Buffers.Views;
Expand Down Expand Up @@ -171,13 +171,13 @@ public Span<T> Span
ThrowObjectDisposedException();
}

#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
ref T r0 = ref array!.DangerousGetReferenceAt(this.start);

// On .NET Core runtimes, we can manually create a span from the starting reference to
// On .NET 6+ runtimes, we can manually create a span from the starting reference to
// skip the argument validations, which include an explicit null check, covariance check
// for the array and the actual validation for the starting offset and target length. We
// only do this on .NET Core as we can leverage the runtime-specific array layout to get
// only do this on .NET 6+ as we can leverage the runtime-specific array layout to get
// a fast access to the initial element, which makes this trick worth it. Otherwise, on
// runtimes where we would need to at least access a static field to retrieve the base
// byte offset within an SZ array object, we can get better performance by just using the
Expand Down
4 changes: 2 additions & 2 deletions CommunityToolkit.HighPerformance/Buffers/SpanOwner{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
using System.Runtime.InteropServices;
#endif
using CommunityToolkit.HighPerformance.Buffers.Views;
Expand Down Expand Up @@ -141,7 +141,7 @@ public Span<T> Span
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
ref T r0 = ref this.array!.DangerousGetReference();

return MemoryMarshal.CreateSpan(ref r0, this.length);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net7.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -47,23 +47,11 @@

<When Condition="'$(TargetFramework)' == 'net6.0' OR '$(TargetFramework)' == 'net7.0'">

<!-- NETSTANDARD2_1_OR_GREATER: includes both .NET Standard 2.1, .NET Core 3.1 and .NET 6.
Additionally, also enable trimming support on .NET 6. -->
<!-- NETSTANDARD2_1_OR_GREATER: includes both .NET Standard 2.1 and .NET 6 and above -->
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
</When>

<When Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>

<!-- .NET Core 3.1 has the Unsafe type, but the version it ships with lacks Unsafe.IsNullRef<T> -->
<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
</ItemGroup>
</When>
</Choose>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

using System;
using System.Runtime.CompilerServices;
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
using System.Runtime.InteropServices;
#endif
using CommunityToolkit.HighPerformance.Enumerables;
Expand Down Expand Up @@ -33,11 +33,6 @@ public static ref T DangerousGetReference<T>(this T[] array)
{
#if NET6_0_OR_GREATER
return ref MemoryMarshal.GetArrayDataReference(array);
#elif NETCOREAPP3_1
RawArrayData? arrayData = Unsafe.As<RawArrayData>(array)!;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);

return ref r0;
#else
IntPtr offset = RuntimeHelpers.GetArrayDataByteOffset<T>();

Expand All @@ -60,12 +55,6 @@ public static ref T DangerousGetReferenceAt<T>(this T[] array, int i)
ref T r0 = ref MemoryMarshal.GetArrayDataReference(array);
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);

return ref ri;
#elif NETCOREAPP3_1
RawArrayData? arrayData = Unsafe.As<RawArrayData>(array)!;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);

return ref ri;
#else
IntPtr offset = RuntimeHelpers.GetArrayDataByteOffset<T>();
Expand All @@ -76,26 +65,6 @@ public static ref T DangerousGetReferenceAt<T>(this T[] array, int i)
#endif
}

#if NETCOREAPP3_1
// Description taken from CoreCLR: see https://source.dot.net/#System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs,285.
// CLR arrays are laid out in memory as follows (multidimensional array bounds are optional):
// [ sync block || pMethodTable || num components || MD array bounds || array data .. ]
// ^ ^ ^ returned reference
// | \-- ref Unsafe.As<RawArrayData>(array).Data
// \-- array
// The base size of an array includes all the fields before the array data,
// including the sync block and method table. The reference to RawData.Data
// points at the number of components, skipping over these two pointer-sized fields.
[StructLayout(LayoutKind.Sequential)]
private sealed class RawArrayData
{
#pragma warning disable CS0649 // Unassigned fields
public IntPtr Length;
public byte Data;
#pragma warning restore CS0649
}
#endif

/// <summary>
/// Counts the number of occurrences of a given value into a target <typeparamref name="T"/> array instance.
/// </summary>
Expand Down
35 changes: 0 additions & 35 deletions CommunityToolkit.HighPerformance/Extensions/ArrayExtensions.2D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ public static ref T DangerousGetReference<T>(this T[,] array)
{
#if NET6_0_OR_GREATER
return ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array));
#elif NETCOREAPP3_1
RawArray2DData? arrayData = Unsafe.As<RawArray2DData>(array)!;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);

return ref r0;
#else
IntPtr offset = RuntimeHelpers.GetArray2DDataByteOffset<T>();

Expand Down Expand Up @@ -65,13 +60,6 @@ public static ref T DangerousGetReferenceAt<T>(this T[,] array, int i, int j)
ref T r0 = ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array));
ref T ri = ref Unsafe.Add(ref r0, index);

return ref ri;
#elif NETCOREAPP3_1
RawArray2DData? arrayData = Unsafe.As<RawArray2DData>(array)!;
nint offset = ((nint)(uint)i * (nint)(uint)arrayData.Width) + (nint)(uint)j;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
ref T ri = ref Unsafe.Add(ref r0, offset);

return ref ri;
#else
int width = array.GetLength(1);
Expand All @@ -84,29 +72,6 @@ public static ref T DangerousGetReferenceAt<T>(this T[,] array, int i, int j)
#endif
}

#if NETCOREAPP3_1
// Description adapted from CoreCLR: see https://source.dot.net/#System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs,285.
// CLR 2D arrays are laid out in memory as follows:
// [ sync block || pMethodTable || Length (padded to IntPtr) || HxW || HxW bounds || array data .. ]
// ^ ^
// | \-- ref Unsafe.As<RawArray2DData>(array).Data
// \-- array
// The length is always padded to IntPtr just like with SZ arrays.
// The total data padding is therefore 20 bytes on x86 (4 + 4 + 4 + 4 + 4), or 24 bytes on x64.
[StructLayout(LayoutKind.Sequential)]
private sealed class RawArray2DData
{
#pragma warning disable CS0649 // Unassigned fields
public IntPtr Length;
public int Height;
public int Width;
public int HeightLowerBound;
public int WidthLowerBound;
public byte Data;
#pragma warning restore CS0649
}
#endif

/// <summary>
/// Returns a <see cref="RefEnumerable{T}"/> over a row in a given 2D <typeparamref name="T"/> array instance.
/// </summary>
Expand Down
33 changes: 0 additions & 33 deletions CommunityToolkit.HighPerformance/Extensions/ArrayExtensions.3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ public static ref T DangerousGetReference<T>(this T[,,] array)
{
#if NET6_0_OR_GREATER
return ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array));
#elif NETCOREAPP3_1
RawArray3DData? arrayData = Unsafe.As<RawArray3DData>(array)!;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);

return ref r0;
#else
IntPtr offset = RuntimeHelpers.GetArray3DDataByteOffset<T>();

Expand Down Expand Up @@ -68,15 +63,6 @@ public static ref T DangerousGetReferenceAt<T>(this T[,,] array, int i, int j, i
ref T r0 = ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array));
ref T ri = ref Unsafe.Add(ref r0, index);

return ref ri;
#elif NETCOREAPP3_1
RawArray3DData? arrayData = Unsafe.As<RawArray3DData>(array)!;
nint offset =
((nint)(uint)i * (nint)(uint)arrayData.Height * (nint)(uint)arrayData.Width) +
((nint)(uint)j * (nint)(uint)arrayData.Width) + (nint)(uint)k;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
ref T ri = ref Unsafe.Add(ref r0, offset);

return ref ri;
#else
int height = array.GetLength(1);
Expand All @@ -92,25 +78,6 @@ public static ref T DangerousGetReferenceAt<T>(this T[,,] array, int i, int j, i
#endif
}

#if NETCOREAPP3_1
// See description for this in the 2D partial file.
// Using the CHW naming scheme here (like with RGB images).
[StructLayout(LayoutKind.Sequential)]
private sealed class RawArray3DData
{
#pragma warning disable CS0649 // Unassigned fields
public IntPtr Length;
public int Channel;
public int Height;
public int Width;
public int ChannelLowerBound;
public int HeightLowerBound;
public int WidthLowerBound;
public byte Data;
#pragma warning restore CS0649
}
#endif

#if NETSTANDARD2_1_OR_GREATER
/// <summary>
/// Creates a new <see cref="Memory{T}"/> over an input 3D <typeparamref name="T"/> array.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static class StringExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref char DangerousGetReference(this string text)
{
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
return ref Unsafe.AsRef(text.GetPinnableReference());
#else
return ref MemoryMarshal.GetReference(text.AsSpan());
Expand All @@ -43,7 +43,7 @@ public static ref char DangerousGetReference(this string text)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref char DangerousGetReferenceAt(this string text, int i)
{
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
ref char r0 = ref Unsafe.AsRef(text.GetPinnableReference());
#else
ref char r0 = ref MemoryMarshal.GetReference(text.AsSpan());
Expand Down
10 changes: 5 additions & 5 deletions CommunityToolkit.HighPerformance/Helpers/BitHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Runtime.CompilerServices;
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
using System.Runtime.Intrinsics.X86;
#endif

Expand Down Expand Up @@ -224,7 +224,7 @@ public static unsafe uint SetFlag(uint value, int n, bool flag)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ExtractRange(uint value, byte start, byte length)
{
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
if (Bmi1.IsSupported)
{
return Bmi1.BitFieldExtract(value, start, length);
Expand Down Expand Up @@ -270,7 +270,7 @@ public static uint SetRange(uint value, byte start, byte length, uint flags)
uint loadMask = highBits << start;
uint storeMask = (flags & highBits) << start;

#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
if (Bmi1.IsSupported)
{
return Bmi1.AndNot(loadMask, value) | storeMask;
Expand Down Expand Up @@ -386,7 +386,7 @@ public static unsafe ulong SetFlag(ulong value, int n, bool flag)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong ExtractRange(ulong value, byte start, byte length)
{
#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
if (Bmi1.X64.IsSupported)
{
return Bmi1.X64.BitFieldExtract(value, start, length);
Expand Down Expand Up @@ -432,7 +432,7 @@ public static ulong SetRange(ulong value, byte start, byte length, ulong flags)
ulong loadMask = highBits << start;
ulong storeMask = (flags & highBits) << start;

#if NETCOREAPP3_1_OR_GREATER
#if NET6_0_OR_GREATER
if (Bmi1.X64.IsSupported)
{
return Bmi1.X64.AndNot(loadMask, value) | storeMask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
#if !NET6_0_OR_GREATER

using System.Runtime.CompilerServices;
#if NETCOREAPP3_1
using System.Runtime.Intrinsics.X86;
using static System.Numerics.BitOperations;
#endif

namespace CommunityToolkit.HighPerformance.Helpers.Internals;

Expand All @@ -29,22 +25,6 @@ internal static class BitOperations
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe uint RoundUpToPowerOf2(uint value)
{
#if NETCOREAPP3_1
if (Lzcnt.IsSupported)
{
if (sizeof(nint) == 8)
{
return (uint)(0x1_0000_0000ul >> LeadingZeroCount(value - 1));
}
else
{
int shift = 32 - LeadingZeroCount(value - 1);

return (1u ^ (uint)(shift >> 5)) << shift;
}
}
#endif

// Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--value;
value |= value >> 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static nint GetArrayNativeLength(Array array)
return (nint)array.LongLength;
}

#if !NETCOREAPP3_1_OR_GREATER
#if !NET6_0_OR_GREATER
/// <summary>
/// Gets the byte offset to the first <typeparamref name="T"/> element in a SZ array.
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ jobs:

# Test solution #

# Run .NET 7 unit tests
- script: dotnet test --no-build -c $(Build.Configuration) -f net7.0 -l "trx;LogFileName=VSTestResults_net7.0.trx"
displayName: Run .NET 7 unit tests

# Run .NET 6 unit tests
- script: dotnet test --no-build -c $(Build.Configuration) -f net6.0 -l "trx;LogFileName=VSTestResults_net6.0.trx"
displayName: Run .NET 6 unit tests

# Run .NET Core 3.1 unit tests
- script: dotnet test --no-build -c $(Build.Configuration) -f netcoreapp3.1 -l "trx;LogFileName=VSTestResults_netcoreapp3.1.trx"
displayName: Run .NET Core 3.1 unit tests

# Run .NET Framework 4.7.2 unit tests
- script: dotnet test --no-build -c $(Build.Configuration) -f net472 -l "trx;LogFileName=VSTestResults_net472.trx"
displayName: Run .NET Framework 4.7.2 unit tests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netcoreapp3.1;net6.0</TargetFrameworks>
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netcoreapp3.1;net6.0</TargetFrameworks>
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading