Skip to content
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
2 changes: 2 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
<add key="dotnet-libraries-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-libraries-transport/nuget/v3/index.json" />
<add key="dotnet10" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10/nuget/v3/index.json" />
<add key="dotnet10-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" />
<!-- Need for prototype Roslyn compiler for runtime-async -->
<add key="general-testing" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json" />
</packageSources>
<auditSources>
<clear />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -19,6 +20,7 @@ public static partial class AsyncHelpers
// It will not capture/restore any local state that is live across it.
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static void AwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : INotifyCompletion
{
ref AsyncHelpers.RuntimeAsyncAwaitState state = ref AsyncHelpers.t_runtimeAsyncAwaitState;
Expand All @@ -34,6 +36,7 @@ public static void AwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : INo
// It will not capture/restore any local state that is live across it.
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static void UnsafeAwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : ICriticalNotifyCompletion
{
ref AsyncHelpers.RuntimeAsyncAwaitState state = ref AsyncHelpers.t_runtimeAsyncAwaitState;
Expand All @@ -48,6 +51,7 @@ public static void UnsafeAwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static T Await<T>(Task<T> task)
{
TaskAwaiter<T> awaiter = task.GetAwaiter();
Expand All @@ -62,6 +66,7 @@ public static T Await<T>(Task<T> task)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static void Await(Task task)
{
TaskAwaiter awaiter = task.GetAwaiter();
Expand All @@ -76,6 +81,7 @@ public static void Await(Task task)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static T Await<T>(ValueTask<T> task)
{
ValueTaskAwaiter<T> awaiter = task.GetAwaiter();
Expand All @@ -90,6 +96,7 @@ public static T Await<T>(ValueTask<T> task)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static void Await(ValueTask task)
{
ValueTaskAwaiter awaiter = task.GetAwaiter();
Expand All @@ -104,6 +111,7 @@ public static void Await(ValueTask task)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static void Await(ConfiguredTaskAwaitable configuredAwaitable)
{
ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter = configuredAwaitable.GetAwaiter();
Expand All @@ -118,6 +126,7 @@ public static void Await(ConfiguredTaskAwaitable configuredAwaitable)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static void Await(ConfiguredValueTaskAwaitable configuredAwaitable)
{
ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter = configuredAwaitable.GetAwaiter();
Expand All @@ -132,6 +141,7 @@ public static void Await(ConfiguredValueTaskAwaitable configuredAwaitable)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static T Await<T>(ConfiguredTaskAwaitable<T> configuredAwaitable)
{
ConfiguredTaskAwaitable<T>.ConfiguredTaskAwaiter awaiter = configuredAwaitable.GetAwaiter();
Expand All @@ -146,6 +156,7 @@ public static T Await<T>(ConfiguredTaskAwaitable<T> configuredAwaitable)
[Intrinsic]
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
[RequiresPreviewFeatures]
public static T Await<T>(ConfiguredValueTaskAwaitable<T> configuredAwaitable)
{
ConfiguredValueTaskAwaitable<T>.ConfiguredValueTaskAwaiter awaiter = configuredAwaitable.GetAwaiter();
Expand All @@ -157,15 +168,25 @@ public static T Await<T>(ConfiguredValueTaskAwaitable<T> configuredAwaitable)
return awaiter.GetResult();
}
#else
[RequiresPreviewFeatures]
public static void UnsafeAwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : ICriticalNotifyCompletion { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static void AwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : INotifyCompletion { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static void Await(System.Threading.Tasks.Task task) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static T Await<T>(System.Threading.Tasks.Task<T> task) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static void Await(System.Threading.Tasks.ValueTask task) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static T Await<T>(System.Threading.Tasks.ValueTask<T> task) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static void Await(System.Runtime.CompilerServices.ConfiguredTaskAwaitable configuredAwaitable) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static void Await(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable configuredAwaitable) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static T Await<T>(System.Runtime.CompilerServices.ConfiguredTaskAwaitable<T> configuredAwaitable) { throw new NotImplementedException(); }
[RequiresPreviewFeatures]
public static T Await<T>(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<T> configuredAwaitable) { throw new NotImplementedException(); }
#endif
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ public static bool IsSupported(string feature)
{
return feature switch
{
PortablePdb or CovariantReturnsOfClasses or ByRefFields or ByRefLikeGenerics or UnmanagedSignatureCallingConvention or DefaultImplementationsOfInterfaces or VirtualStaticsInInterfaces or NumericIntPtr => true,
PortablePdb or
CovariantReturnsOfClasses or
ByRefFields or
ByRefLikeGenerics or
UnmanagedSignatureCallingConvention or
DefaultImplementationsOfInterfaces or
VirtualStaticsInInterfaces or
NumericIntPtr => true,

nameof(IsDynamicCodeSupported) => IsDynamicCodeSupported,
nameof(IsDynamicCodeCompiled) => IsDynamicCodeCompiled,
_ => false,
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13833,15 +13833,25 @@ public static void RunModuleConstructor(System.ModuleHandle module) { }
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5007", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public static partial class AsyncHelpers
{
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static void UnsafeAwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : ICriticalNotifyCompletion { }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static void AwaitAwaiter<TAwaiter>(TAwaiter awaiter) where TAwaiter : INotifyCompletion { }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static void Await(System.Threading.Tasks.Task task) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static T Await<T>(System.Threading.Tasks.Task<T> task) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static void Await(System.Threading.Tasks.ValueTask task) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static T Await<T>(System.Threading.Tasks.ValueTask<T> task) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static void Await(System.Runtime.CompilerServices.ConfiguredTaskAwaitable configuredAwaitable) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static void Await(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable configuredAwaitable) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static T Await<T>(System.Runtime.CompilerServices.ConfiguredTaskAwaitable<T> configuredAwaitable) { throw null; }
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute]
public static T Await<T>(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<T> configuredAwaitable) { throw null; }
}
public sealed partial class RuntimeWrappedException : System.Exception
Expand Down
5 changes: 5 additions & 0 deletions src/tests/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
<Import Project="$(MSBuildThisFileDirectory)\Common\dir.sdkbuild.props" Condition="'$(UsingMicrosoftNETSdk)' == 'true'" />
<Import Project="$(MSBuildThisFileDirectory)\Common\dir.common.props" Condition="'$(UsingMicrosoftNETSdk)' != 'true'" />

<PropertyGroup>
<!-- Override the compiler version with a private build that supports runtime-async -->
<MicrosoftNetCompilersToolsetVersion>5.0.0-1.25259.6</MicrosoftNetCompilersToolsetVersion>
</PropertyGroup>
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason to have this in src/tests/Directory.Build.props instead of src/tests/async/Directory.Build.props?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think this worked when I tried it earlier. Let me try again.

Copy link
Member

Choose a reason for hiding this comment

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

It needs to be here because we don't restore individual test projects (there's too many). Instead we restore the test_dependencies projects and point the individual test projects at those restore results.

One day I'll get this cleaned up I hope.


<PropertyGroup>
<RunningOnUnix Condition="('$(RunningOnUnix)' == '') And ('$(MSBuildRuntimeType)' == 'Core') And ('$(OS)'!='Windows_NT')">true</RunningOnUnix>
</PropertyGroup>
Expand Down
4 changes: 4 additions & 0 deletions src/tests/async/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@
<RunAnalyzers>true</RunAnalyzers>
<NoWarn>$(NoWarn);xUnit1013</NoWarn>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<Features>$(Features);runtime-async=on</Features>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)RuntimeAsyncMethodGenerationAttribute.cs" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions src/tests/async/RuntimeAsyncMethodGenerationAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Method)]
public class RuntimeAsyncMethodGenerationAttribute(bool runtimeAsync) : Attribute
{
public bool RuntimeAsync { get; } = runtimeAsync;
}
7 changes: 4 additions & 3 deletions src/tests/async/awaitingnotasync/awaitingnotasync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Xunit;

Expand All @@ -14,13 +13,15 @@ public static void TestEntryPoint()
AsyncEntryPoint().Wait();
}

[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
private static async Task<T> GetTask<T>(T arg)
{
await Task.Yield();
return arg;
}

// TODO: switch every other scenario to use ValueTask
[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
private static async ValueTask<T> GetValueTask<T>(T arg)
{
await Task.Yield();
Expand All @@ -33,13 +34,13 @@ private static async ValueTask<T> GetValueTask<T>(T arg)

private static T sIdentity<T>(T arg) => arg;

private static async2 Task AsyncEntryPoint()
private static async Task AsyncEntryPoint()
{
// static field
sField = GetTask(5);
Assert.Equal(5, await sField);

// property
// property
Assert.Equal(6, await sProp);

// generic identity
Expand Down
6 changes: 3 additions & 3 deletions src/tests/async/collectible-alc/collectible-alc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static void TestEntryPoint()
AsyncEntryPoint().Wait();
}

private static async2 Task AsyncEntryPoint()
private static async Task AsyncEntryPoint()
{
WeakReference wr = await CallFooAsyncAndUnload();

Expand All @@ -31,7 +31,7 @@ private static async2 Task AsyncEntryPoint()
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static async2 Task<WeakReference> CallFooAsyncAndUnload()
private static async Task<WeakReference> CallFooAsyncAndUnload()
{
TaskCompletionSource tcs = new();
(Task<string> task, WeakReference wr) = CallFooAsyncInCollectibleALC(tcs.Task);
Expand Down Expand Up @@ -63,7 +63,7 @@ private static (Task<string>, WeakReference) CallFooAsyncInCollectibleALC(Task t
}

// Task[] to work around a compiler bug
private static async2 Task<string> FooAsync(Task[] t)
private static async Task<string> FooAsync(Task[] t)
{
await t[0];
return "done";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ public static void TestEntryPoint()
Assert.Equal(199_990_000, arr[0]);
}

[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
private static async Task AsyncTestEntryPoint(int[] arr, int index)
{
await HoistedByref(arr, index);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static async2 Task<int> HoistedByref(int[] arr, int index)
private static async Task<int> HoistedByref(int[] arr, int index)
{
for (int i = 0; i < 20000; i++)
{
Expand Down
10 changes: 7 additions & 3 deletions src/tests/async/eh-microbench/eh-microbench.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public static int Main()
return 100;
}

[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
public static async Task AsyncEntry()
{
if (!GCSettings.IsServerGC)
Expand Down Expand Up @@ -68,6 +69,7 @@ public static async Task AsyncEntry()
await RunBench(yieldFrequency, depth, finallyRate, throwOrReturn, "ValueTask");
}

[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
private static async Task RunBench(int yieldCount, int depth, int finallyRate, bool throwOrReturn, string type)
{

Expand Down Expand Up @@ -104,7 +106,7 @@ public Benchmark(int yieldCount, int depth, int finallyRate, bool throwOrReturn)
_throwOrReturn = throwOrReturn;
}

public async2 Task<long> Run(string type)
public async Task<long> Run(string type)
{
if (type == "Async2")
return await RunAsync2(_depth);
Expand All @@ -117,6 +119,7 @@ public async2 Task<long> Run(string type)
return 0;
}

[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
public async Task<long> RunTask(int depth)
{
int liveState1 = depth * 3 + _yieldCount;
Expand Down Expand Up @@ -182,6 +185,7 @@ public async Task<long> RunTask(int depth)
return result;
}

[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
public async ValueTask<long> RunValueTask(int depth)
{
int liveState1 = depth * 3 + _yieldCount;
Expand Down Expand Up @@ -267,7 +271,7 @@ public class FakeThread
// This case is used to test the impact of save/restore of the sync and execution context on performance
// The intent here is to measure what the performance impact of maintaining the current async semantics with
// the new implementation.
public async2 Task<long> RunAsync2WithContextSaveRestore(int depth)
public async Task<long> RunAsync2WithContextSaveRestore(int depth)
{
FakeThread thread = CurrentThread;
if (thread == null)
Expand Down Expand Up @@ -361,7 +365,7 @@ public async2 Task<long> RunAsync2WithContextSaveRestore(int depth)
}
}

public async2 Task<long> RunAsync2(int depth)
public async Task<long> RunAsync2(int depth)
{
int liveState1 = depth * 3 + _yieldCount;
int liveState2 = depth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Diagnostics;
using Xunit;
Expand All @@ -22,7 +23,7 @@ public static void Test()
System.Console.WriteLine("allocated: " + allocated);
}

public static async2 Task AsyncEntry()
public static async Task AsyncEntry()
{
for (int i = 0; i < iterations; i++)
{
Expand All @@ -34,7 +35,7 @@ public static async2 Task AsyncEntry()
}
}

static async2 Task<int> Fib(int i)
static async Task<int> Fib(int i)
{
if (i <= 1)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Xunit;

public class Async2FibonacceWithYields
Expand Down Expand Up @@ -34,7 +35,7 @@ public struct MyInt
public MyInt(int i) => this.i = i;
}

public static async2 Task AsyncEntry()
public static async Task AsyncEntry()
{
for (int i = 0; i < iterations; i++)
{
Expand All @@ -46,7 +47,7 @@ public static async2 Task AsyncEntry()
}
}

static async2 Task<MyInt> Fib(MyInt n)
static async Task<MyInt> Fib(MyInt n)
{
int i = n.i;
if (i <= 1)
Expand Down
Loading
Loading