From eb9bfb1607bcb7f681ca3eda670982b16fec96c7 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 11 Sep 2017 14:40:57 -0700 Subject: [PATCH] Use AsyncTaskCache in ValueTask.AsTask() We can avoid task allocations for common values by using the same task cache that async methods do. This is important to avoid allocations in certain cases when switching from Task-returning to ValueTask-returning methods. If at some point we change Task.FromResult to use the same cache, this can be reverted. --- src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs | 2 +- src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs b/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs index 4953880..384e4a8 100644 --- a/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs +++ b/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs @@ -114,7 +114,7 @@ namespace System.Threading.Tasks // Return the task if we were constructed from one, otherwise manufacture one. We don't // cache the generated task into _task as it would end up changing both equality comparison // and the hash code we generate in GetHashCode. - _task ?? Task.FromResult(_result); + _task ?? AsyncTaskMethodBuilder.GetTaskForResult(_result); /// Gets whether the represents a completed operation. public bool IsCompleted => _task == null || _task.IsCompleted; diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index 4e4de98..eb198ba 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -719,7 +719,7 @@ namespace System.Runtime.CompilerServices /// The result for which we need a task. /// The completed task containing the result. [MethodImpl(MethodImplOptions.AggressiveInlining)] // method looks long, but for a given TResult it results in a relatively small amount of asm - private Task GetTaskForResult(TResult result) + internal static Task GetTaskForResult(TResult result) { Contract.Ensures( EqualityComparer.Default.Equals(result, Contract.Result>().Result), -- 2.7.4