Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public enum ReadyToRunImportSectionFlags : ushort
/// Constants for method and field encoding
/// </summary>
[Flags]
public enum ReadyToRunMethodSigFlags : byte
public enum ReadyToRunMethodSigFlags : ushort
{
READYTORUN_METHOD_SIG_None = 0x00,
READYTORUN_METHOD_SIG_UnboxingStub = 0x01,
Expand All @@ -52,6 +52,7 @@ public enum ReadyToRunMethodSigFlags : byte
READYTORUN_METHOD_SIG_Constrained = 0x20,
READYTORUN_METHOD_SIG_OwnerType = 0x40,
READYTORUN_METHOD_SIG_UpdateContext = 0x80,
READYTORUN_METHOD_SIG_AsyncThunkVariant = 0x100,
Copy link
Member

Choose a reason for hiding this comment

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

Should this be just AsyncVariant (ie cover both Thunk or impl)?

This enum is part of R2R file format. It is used to encode references to methods in other assemblies. This encoding should be resilient to compatible changes in the implementation of other assemblies. If we encode AsyncThunkVariant here, it does not sound like we will be resilient to the implementations in other assemblies changing between async v1 and async v2.

Copy link
Member

Choose a reason for hiding this comment

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

Is READYTORUN_METHOD_SIG_SlotInsteadOfToken used? Could we reuse it (bumping the R2R version of course)?

}

[Flags]
Expand Down
109 changes: 0 additions & 109 deletions src/coreclr/tools/Common/JitInterface/AsyncMethodDesc.cs

This file was deleted.

24 changes: 0 additions & 24 deletions src/coreclr/tools/Common/JitInterface/AsyncMethodDescFactory.cs

This file was deleted.

11 changes: 8 additions & 3 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,11 @@ private MethodDesc MethodBeingCompiled
{
get
{
#if READYTORUN
return _methodCodeNode.GetJitMethod(_asyncMethodFactory);
Copy link
Member

Choose a reason for hiding this comment

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

Would it be better to inline the contents of GetJitMethod to here? Presumably MethodWithGCInfo doesn't really need to know about AsyncMethodVariantFactory.

#else
return _methodCodeNode.Method;
#endif
}
}

Expand Down Expand Up @@ -877,6 +881,7 @@ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* s

if (!signature.IsStatic) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_HASTHIS;
if (signature.IsExplicitThis) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_EXPLICITTHIS;
if (signature.IsAsyncCallConv) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_ASYNCCALL;

TypeDesc returnType = signature.ReturnType;

Expand Down Expand Up @@ -1395,7 +1400,7 @@ private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info)

if (info->pResolvedTokenVirtualMethod != null)
{
methodWithTokenDecl = ComputeMethodWithToken(decl, ref *info->pResolvedTokenVirtualMethod, null, false);
methodWithTokenDecl = ComputeMethodWithToken(decl, ref *info->pResolvedTokenVirtualMethod, null, false, asyncVariant: false);
Copy link
Member

Choose a reason for hiding this comment

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

I think the asyncVariant: false here are not quite correct

I would make this throw RequiresRuntimeJitException if decl.IsAsync or impl.IsAsync. for now.

}
else
{
Expand All @@ -1410,7 +1415,7 @@ private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info)
info->detail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_DECL_NOT_REPRESENTABLE;
return false;
}
methodWithTokenDecl = new MethodWithToken(decl, declToken, null, false, null, devirtualizedMethodOwner: decl.OwningType);
methodWithTokenDecl = new MethodWithToken(decl, declToken, null, false, asyncVariant: false, null, devirtualizedMethodOwner: decl.OwningType);
}
MethodWithToken methodWithTokenImpl;
#endif
Expand All @@ -1436,7 +1441,7 @@ private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info)
else
{
#if READYTORUN
methodWithTokenImpl = new MethodWithToken(nonUnboxingImpl, resolver.GetModuleTokenForMethod(nonUnboxingImpl.GetTypicalMethodDefinition(), allowDynamicallyCreatedReference: false, throwIfNotFound: true), null, unboxingStub, null, devirtualizedMethodOwner: impl.OwningType);
methodWithTokenImpl = new MethodWithToken(nonUnboxingImpl, resolver.GetModuleTokenForMethod(nonUnboxingImpl.GetTypicalMethodDefinition(), allowDynamicallyCreatedReference: false, throwIfNotFound: true), null, unboxingStub, asyncVariant: false, null, devirtualizedMethodOwner: impl.OwningType);
#endif

info->resolvedTokenDevirtualizedMethod = CreateResolvedTokenFromMethod(this, impl
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public unsafe struct CORINFO_SIG_INFO
private uint totalILArgs() { return (uint)(numArgs + (hasImplicitThis() ? 1 : 0)); }
private bool isVarArg() { return ((getCallConv() == CorInfoCallConv.CORINFO_CALLCONV_VARARG) || (getCallConv() == CorInfoCallConv.CORINFO_CALLCONV_NATIVEVARARG)); }
internal bool hasTypeArg() { return ((callConv & CorInfoCallConv.CORINFO_CALLCONV_PARAMTYPE) != 0); }
private bool isAsyncCallConv() { return ((callConv & CorInfoCallConv.CORINFO_CALLCONV_ASYNCCALL) != 0); }
};

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -377,6 +378,7 @@ public enum CorInfoCallConv
CORINFO_CALLCONV_HASTHIS = 0x20,
CORINFO_CALLCONV_EXPLICITTHIS = 0x40,
CORINFO_CALLCONV_PARAMTYPE = 0x80, // Passed last. Same as CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG
CORINFO_CALLCONV_ASYNCCALL = 0x100, // Is this a call to an async function?
}

// Represents the calling conventions supported with the extensible calling convention syntax
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/tools/Common/JitInterface/UnboxingMethodDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ public override MethodDesc InstantiateSignature(Instantiation typeInstantiation,
return this;
}

public override AsyncMethodKind AsyncMethodKind
{
get
{
return _wrappedMethod.AsyncMethodKind;
}
}

public override string ToString()
{
return "Unboxing MethodDesc: " + _wrappedMethod.ToString();
Expand Down
138 changes: 138 additions & 0 deletions src/coreclr/tools/Common/TypeSystem/Common/AsyncMethodVariant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Internal.JitInterface;


namespace Internal.TypeSystem
{
/// <summary>
/// Either the AsyncMethodImplVariant or AsyncMethodThunkVariant of a method marked .IsAsync.
/// </summary>
public partial class AsyncMethodVariant : MethodDelegator, IJitHashableOnly
{
private readonly AsyncMethodVariantFactory _factory;
private readonly AsyncMethodKind _asyncMethodKind;
private readonly int _jitVisibleHashCode;
private MethodSignature _asyncSignature;

public AsyncMethodVariant(MethodDesc wrappedMethod, AsyncMethodVariantFactory factory, AsyncMethodKind kind)
: base(wrappedMethod)
{
Debug.Assert(wrappedMethod.IsTaskReturning);
Debug.Assert(kind switch
{
AsyncMethodKind.AsyncVariantThunk => !wrappedMethod.IsAsync,
AsyncMethodKind.AsyncVariantImpl => wrappedMethod.IsAsync,
_ => false,
});
Comment on lines +26 to +31
Copy link
Member

Choose a reason for hiding this comment

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

Do we need the kind parameter? We can deduce the kind from the wrappedMethod. It would simplify the Factory too.

_factory = factory;
_asyncMethodKind = kind;
_jitVisibleHashCode = HashCode.Combine(wrappedMethod.GetHashCode(), 0x310bb74f);
}

public MethodDesc Target => _wrappedMethod;

public override AsyncMethodKind AsyncMethodKind => _asyncMethodKind;

public override MethodSignature Signature
{
get
{
return _asyncSignature ??= _wrappedMethod.Signature.CreateAsyncSignature();
Copy link
Member

Choose a reason for hiding this comment

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

Inline CreateAsyncSignature to here? It doesn't feel like a MethodSignature concern.

}
}

public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
{
return _factory.GetOrCreateAsyncMethodImplVariant(_wrappedMethod.GetCanonMethodTarget(kind), _asyncMethodKind);
}

public override MethodDesc GetMethodDefinition()
{
var real = _wrappedMethod.GetMethodDefinition();
if (real == _wrappedMethod)
return this;

return _factory.GetOrCreateAsyncMethodImplVariant(real, _asyncMethodKind);
}

public override MethodDesc GetTypicalMethodDefinition()
{
var real = _wrappedMethod.GetTypicalMethodDefinition();
if (real == _wrappedMethod)
return this;
return _factory.GetOrCreateAsyncMethodImplVariant(real, _asyncMethodKind);
}

public override MethodDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation)
{
var real = _wrappedMethod.InstantiateSignature(typeInstantiation, methodInstantiation);
if (real == _wrappedMethod)
return this;
return _factory.GetOrCreateAsyncMethodImplVariant(real, _asyncMethodKind);
}

public override string ToString() => $"Async variant ({_asyncMethodKind}): " + _wrappedMethod.ToString();

protected override int ClassCode => throw new NotImplementedException();

protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
throw new NotImplementedException();
}

protected override int ComputeHashCode()
{
throw new NotSupportedException("This method may not be stored as it is expected to only be used transiently in the JIT");
}

int IJitHashableOnly.GetJitVisibleHashCode() => _jitVisibleHashCode;
}

public sealed class AsyncMethodVariantFactory : Dictionary<(MethodDesc, AsyncMethodKind), AsyncMethodVariant>
{
public AsyncMethodVariant GetOrCreateAsyncMethodImplVariant(MethodDesc wrappedMethod, AsyncMethodKind kind)
{
Debug.Assert(wrappedMethod.IsAsync);
if (!TryGetValue((wrappedMethod, kind), out AsyncMethodVariant variant))
{
variant = new AsyncMethodVariant(wrappedMethod, this, kind);
this[(wrappedMethod, kind)] = variant;
}
return variant;
}

public AsyncMethodVariant GetOrCreateAsyncThunk(MethodDesc wrappedMethod)
{
return GetOrCreateAsyncMethodImplVariant(wrappedMethod, AsyncMethodKind.AsyncVariantThunk);
}

public AsyncMethodVariant GetOrCreateAsyncImpl(MethodDesc wrappedMethod)
{
return GetOrCreateAsyncMethodImplVariant(wrappedMethod, AsyncMethodKind.AsyncVariantImpl);
}
}

public static class AsyncMethodVariantExtensions
{
/// <summary>
/// Returns true if this MethodDesc is an AsyncMethodVariant, which should not escape the jit interface.
/// </summary>
public static bool IsAsyncVariant(this MethodDesc method)
{
return method is AsyncMethodVariant;
}

/// <summary>
/// Gets the wrapped method of the AsyncMethodVariant. This method is Task-returning.
/// </summary>
public static MethodDesc GetAsyncVariantDefinition(this MethodDesc method)
{
return ((AsyncMethodVariant)method).Target;
}
Comment on lines +130 to +136
Copy link
Member

Choose a reason for hiding this comment

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

Is this used?

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Threading;

namespace Internal.TypeSystem
{
public sealed partial class InstantiatedMethod
{
public override AsyncMethodKind AsyncMethodKind
{
get
{
return _methodDef.AsyncMethodKind;
}
}
}
}
Loading
Loading