Skip to content

Commit

Permalink
Async-streams: use ManualResetValueTaskSourceCore and AsyncIteratorMe…
Browse files Browse the repository at this point in the history
…thodBuilder types (#31330)
  • Loading branch information
jcouv committed Dec 4, 2018
1 parent a5cef4a commit 9dcc089
Show file tree
Hide file tree
Showing 11 changed files with 473 additions and 447 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ namespace Microsoft.CodeAnalysis.CSharp
/// </summary>
internal sealed class AsyncIteratorInfo
{
// This `ManualResetValueTaskSourceLogic<bool>` struct implements the `IValueTaskSource` logic
// This `ManualResetValueTaskSourceCore<bool>` struct implements the `IValueTaskSource` logic
internal FieldSymbol PromiseOfValueOrEndField { get; }

// Stores the current/yielded value
internal FieldSymbol CurrentField { get; }

// Method to fulfill the promise with a result: `void ManualResetValueTaskSourceLogic<T>.SetResult(T result)`
// Method to fulfill the promise with a result: `void ManualResetValueTaskSourceCore<T>.SetResult(T result)`
internal MethodSymbol SetResultMethod { get; }

// Method to fulfill the promise with an exception: `void ManualResetValueTaskSourceLogic<T>.SetException(Exception error)`
// Method to fulfill the promise with an exception: `void ManualResetValueTaskSourceCore<T>.SetException(Exception error)`
internal MethodSymbol SetExceptionMethod { get; }

public AsyncIteratorInfo(FieldSymbol promiseOfValueOrEndField, FieldSymbol currentField,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,41 @@ internal struct AsyncMethodBuilderMemberCollection

internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection)
{
if (method.IsVoidReturningAsync() || method.IsIterator)
if (method.IsIterator)
{
var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder);
Debug.Assert((object)builderType != null);

TryGetBuilderMember<MethodSymbol>(
F,
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Create,
builderType,
customBuilder: false,
out MethodSymbol createBuilderMethod);

if (createBuilderMethod is null)
{
collection = default;
return false;
}

return TryCreate(
F,
customBuilder: false,
builderType: builderType,
resultType: F.SpecialType(SpecialType.System_Void),
createBuilderMethod: createBuilderMethod,
taskProperty: null,
setException: null, // unused
setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Complete,
awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitOnCompleted,
awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitUnsafeOnCompleted,
start: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T,
setStateMachine: null, // unused
collection: out collection);
}

if (method.IsVoidReturningAsync())
{
var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder);
Debug.Assert((object)builderType != null);
Expand Down Expand Up @@ -151,7 +185,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
bool customBuilder = returnType.IsCustomTaskType(out builderArgument);
if (customBuilder)
{
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric:false);
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false);
if ((object)builderType != null)
{
taskProperty = GetCustomTaskProperty(F, builderType, returnType);
Expand Down Expand Up @@ -219,7 +253,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
bool customBuilder = returnType.IsCustomTaskType(out builderArgument);
if (customBuilder)
{
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric:true);
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true);
if ((object)builderType != null)
{
builderType = builderType.ConstructedFrom.Construct(resultType);
Expand Down Expand Up @@ -300,12 +334,12 @@ private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F,
TypeSymbol resultType,
MethodSymbol createBuilderMethod,
PropertySymbol taskProperty,
WellKnownMember setException,
WellKnownMember? setException,
WellKnownMember setResult,
WellKnownMember awaitOnCompleted,
WellKnownMember awaitUnsafeOnCompleted,
WellKnownMember start,
WellKnownMember setStateMachine,
WellKnownMember? setStateMachine,
out AsyncMethodBuilderMemberCollection collection)
{
MethodSymbol setExceptionMethod;
Expand Down Expand Up @@ -344,15 +378,22 @@ private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F,

private static bool TryGetBuilderMember<TSymbol>(
SyntheticBoundNodeFactory F,
WellKnownMember member,
WellKnownMember? member,
NamedTypeSymbol builderType,
bool customBuilder,
out TSymbol symbol)
where TSymbol : Symbol
{
if (!member.HasValue)
{
symbol = null;
return true;
}

WellKnownMember memberValue = member.Value;
if (customBuilder)
{
var descriptor = WellKnownMembers.GetDescriptor(member);
var descriptor = WellKnownMembers.GetDescriptor(memberValue);
var sym = CSharpCompilation.GetRuntimeMember(
builderType.OriginalDefinition,
ref descriptor,
Expand All @@ -366,15 +407,15 @@ private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F,
}
else
{
symbol = F.WellKnownMember(member, isOptional: true) as TSymbol;
symbol = F.WellKnownMember(memberValue, isOptional: true) as TSymbol;
if ((object)symbol != null)
{
symbol = (TSymbol)symbol.SymbolAsMember(builderType);
}
}
if ((object)symbol == null)
{
var descriptor = WellKnownMembers.GetDescriptor(member);
var descriptor = WellKnownMembers.GetDescriptor(memberValue);
var diagnostic = new CSDiagnostic(
new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, (customBuilder ? (object)builderType : descriptor.DeclaringTypeMetadataName), descriptor.Name),
F.Syntax.Location);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,17 @@ protected override void VerifyPresenceOfRequiredAPIs(DiagnosticBag bag)
EnsureWellKnownMember(WellKnownMember.System_IAsyncDisposable__DisposeAsync, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ValueTask_T__ctor, bag);

EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__ctor, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__GetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__GetStatus, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__get_Version, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__OnCompleted, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__Reset, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__SetException, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__SetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetStatus, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__get_Version, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__OnCompleted, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__SetException, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__SetResult, bag);

EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__GetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__GetStatus, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__OnCompleted, bag);

EnsureWellKnownMember(WellKnownMember.System_Runtime_CompilerServices_IStrongBox_T__get_Value, bag);
EnsureWellKnownMember(WellKnownMember.System_Runtime_CompilerServices_IStrongBox_T__Value, bag);
}

protected override void GenerateMethodImplementations()
Expand All @@ -88,9 +84,6 @@ protected override void GenerateMethodImplementations()
GenerateIValueTaskSourceImplementation_GetStatus();
GenerateIValueTaskSourceImplementation_OnCompleted();

// IStrongBox<ManualResetValueTaskSourceLogic<TResult>>
GenerateIStrongBox_get_Value();

// IAsyncDisposable
GenerateIAsyncDisposable_DisposeAsync();
}
Expand All @@ -107,7 +100,7 @@ protected override void GenerateControlFields()

// Add a field: ManualResetValueTaskSourceLogic<bool> promiseOfValueOrEnd
_promiseOfValueOrEndField = F.StateMachineField(
F.WellKnownType(WellKnownType.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T).Construct(boolType),
F.WellKnownType(WellKnownType.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T).Construct(boolType),
GeneratedNames.MakeAsyncIteratorPromiseOfValueOrEndFieldName(), isPublic: true);

// the element type may contain method type parameters, which are now alpha-renamed into type parameters of the generated class
Expand All @@ -125,7 +118,6 @@ protected override void GenerateConstructor()
// this.state = state;
// this.initialThreadId = {managedThreadId};
// this.builder = System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create();
// this.valueOrEndPromise = new ManualResetValueTaskSourceLogic<bool>(this);
// }
Debug.Assert(stateMachineType.Constructor is IteratorConstructor);

Expand Down Expand Up @@ -153,16 +145,6 @@ protected override void GenerateConstructor()
null,
methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder)));

// this._valueOrEndPromise = new ManualResetValueTaskSourceLogic<bool>(this);
MethodSymbol mrvtslCtor =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__ctor)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

bodyBuilder.Add(
F.Assignment(
F.Field(F.This(), _promiseOfValueOrEndField),
F.New(mrvtslCtor, F.This())));

bodyBuilder.Add(F.Return());
F.CloseMethod(F.Block(bodyBuilder.ToImmutableAndFree()));
bodyBuilder = null;
Expand Down Expand Up @@ -218,7 +200,7 @@ private void GenerateIAsyncEnumeratorImplementation_MoveNextAsync()

// _promiseOfValueOrEnd.Reset();
BoundFieldAccess promiseField = F.Field(F.This(), _promiseOfValueOrEndField);
var resetMethod = (MethodSymbol)F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__Reset, isOptional: true)
var resetMethod = (MethodSymbol)F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset, isOptional: true)
.SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

var callReset = F.ExpressionStatement(F.Call(promiseField, resetMethod));
Expand All @@ -239,7 +221,7 @@ private void GenerateIAsyncEnumeratorImplementation_MoveNextAsync()
.AsMember((NamedTypeSymbol)IAsyncEnumerableOfElementType_MoveNextAsync.ReturnType.TypeSymbol);

MethodSymbol promise_get_Version =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__get_Version)
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__get_Version)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

// return new ValueTask<bool>(this, _valueOrEndPromise.Version);
Expand Down Expand Up @@ -289,7 +271,7 @@ private void GenerateIValueTaskSourceImplementation_GetResult()
.AsMember(IValueTaskSourceOfBool);

MethodSymbol promise_GetResult =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__GetResult)
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetResult)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

// The implementation doesn't depend on the method body of the iterator method.
Expand All @@ -314,7 +296,7 @@ private void GenerateIValueTaskSourceImplementation_GetStatus()
.AsMember(IValueTaskSourceOfBool);

MethodSymbol promise_GetStatus =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__GetStatus)
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetStatus)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

// The implementation doesn't depend on the method body of the iterator method.
Expand All @@ -340,7 +322,7 @@ private void GenerateIValueTaskSourceImplementation_OnCompleted()
.AsMember(IValueTaskSourceOfBool);

MethodSymbol promise_OnCompleted =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__OnCompleted)
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__OnCompleted)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

// The implementation doesn't depend on the method body of the iterator method.
Expand All @@ -357,29 +339,6 @@ private void GenerateIValueTaskSourceImplementation_OnCompleted()
F.Return())); // return;
}

private void GenerateIStrongBox_get_Value()
{
// Produce the implementation for `ref ManualResetValueTaskSourceLogic<bool> IStrongBox<ManualResetValueTaskSourceLogic<bool>>.Value { get; }`:
// return ref _valueOrEndPromise;

NamedTypeSymbol MrvtslOfBool =
F.WellKnownType(WellKnownType.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T)
.Construct(F.SpecialType(SpecialType.System_Boolean));

NamedTypeSymbol IStrongBoxOfMrvtslOfBool =
F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_IStrongBox_T)
.Construct(MrvtslOfBool);

MethodSymbol IStrongBoxOfMrvtslOfBool_get_Value =
F.WellKnownMethod(WellKnownMember.System_Runtime_CompilerServices_IStrongBox_T__get_Value)
.AsMember(IStrongBoxOfMrvtslOfBool);

OpenPropertyImplementation(IStrongBoxOfMrvtslOfBool_get_Value);

// return ref _valueOrEndPromise;
F.CloseMethod(F.Return(F.Field(F.This(), _promiseOfValueOrEndField)));
}

private void GenerateIAsyncDisposable_DisposeAsync()
{
// Produce the implementation of `ValueTask IAsyncDisposable.DisposeAsync()`:
Expand All @@ -401,7 +360,7 @@ private void GenerateIAsyncDisposable_DisposeAsync()
var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance();

MethodSymbol promise_Reset =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__Reset)
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);

bodyBuilder.Add(
Expand Down Expand Up @@ -446,13 +405,13 @@ private void GenerateIAsyncEnumerableImplementation_GetAsyncEnumerator()

protected override void GenerateMoveNext(SynthesizedImplementationMethod moveNextMethod)
{
MethodSymbol setResultMethod = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__SetResult, isOptional: true);
MethodSymbol setResultMethod = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__SetResult, isOptional: true);
if ((object)setResultMethod != null)
{
setResultMethod = (MethodSymbol)setResultMethod.SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);
}

MethodSymbol setExceptionMethod = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ManualResetValueTaskSourceLogic_T__SetException, isOptional: true);
MethodSymbol setExceptionMethod = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__SetException, isOptional: true);
if ((object)setExceptionMethod != null)
{
setExceptionMethod = (MethodSymbol)setExceptionMethod.SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type.TypeSymbol);
Expand Down
Loading

0 comments on commit 9dcc089

Please sign in to comment.