forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAsyncMethodDesc.cs
More file actions
118 lines (105 loc) · 4.4 KB
/
Copy pathAsyncMethodDesc.cs
File metadata and controls
118 lines (105 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// 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.Diagnostics;
using Internal.TypeSystem;
namespace Internal.JitInterface
{
/// <summary>
/// Represents the async-callable (CORINFO_CALLCONV_ASYNCCALL) variant of a Task/ValueTask returning method.
/// </summary>
internal sealed class AsyncMethodDesc : MethodDelegator
{
private readonly AsyncMethodDescFactory _factory;
private readonly int _jitVisibleHashCode;
public MethodDesc Target => _wrappedMethod;
public AsyncMethodDesc(MethodDesc wrappedMethod, AsyncMethodDescFactory factory)
: base(wrappedMethod)
{
Debug.Assert(wrappedMethod.IsTaskReturning());
_factory = factory;
// Salt with arbitrary constant so hash space differs from underlying method.
_jitVisibleHashCode = HashCode.Combine(wrappedMethod.GetHashCode(), 0x51C0A54);
}
public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind)
{
MethodDesc realCanonTarget = _wrappedMethod.GetCanonMethodTarget(kind);
if (realCanonTarget != _wrappedMethod)
return _factory.GetAsyncMethod(realCanonTarget);
return this;
}
public override MethodDesc GetMethodDefinition()
{
MethodDesc real = _wrappedMethod.GetMethodDefinition();
if (real != _wrappedMethod)
return _factory.GetAsyncMethod(real);
return this;
}
public override MethodDesc GetTypicalMethodDefinition()
{
MethodDesc real = _wrappedMethod.GetTypicalMethodDefinition();
return real;
//if (real != _wrappedMethod)
// return _factory.GetAsyncMethod(real);
//return this;
}
public override MethodDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation)
{
MethodDesc real = _wrappedMethod.InstantiateSignature(typeInstantiation, methodInstantiation);
if (real != _wrappedMethod)
return _factory.GetAsyncMethod(real);
return this;
}
public override MethodSignature Signature
{
get
{
MethodSignature wrappedSignature = _wrappedMethod.Signature;
MetadataType md = (MetadataType)wrappedSignature.ReturnType;
MethodSignatureBuilder builder = new MethodSignatureBuilder(wrappedSignature);
builder.ReturnType = md.HasInstantiation ? md.Instantiation[0] : this.Context.GetWellKnownType(WellKnownType.Void);
builder.Flags = wrappedSignature.Flags | MethodSignatureFlags.AsyncCallConv;
return builder.ToSignature();
}
}
protected override int ClassCode => 0x554d08b9;
protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
if (other is AsyncMethodDesc otherAsync)
{
return comparer.Compare(_wrappedMethod, otherAsync._wrappedMethod);
}
return -1;
}
public override string ToString()
{
return "Async MethodDesc: " + _wrappedMethod.ToString();
}
}
internal static class AsyncMethodDescExtensions
{
public static bool IsAsyncCallConv(this MethodDesc method)
{
return method is AsyncMethodDesc;
}
/// <summary>
/// Returns true if the method returns Task, Task<T>, ValueTask, or ValueTask<T>, otherwise false.
/// </summary>
public static bool IsTaskReturning(this MethodDesc method)
{
TypeDesc ret = method.GetTypicalMethodDefinition().Signature.ReturnType;
if (ret is MetadataType md
&& md.Module == method.Context.SystemModule
&& md.Namespace.SequenceEqual("System.Threading.Tasks"u8))
{
ReadOnlySpan<byte> name = md.Name;
if (name.SequenceEqual("Task"u8) || name.SequenceEqual("Task`1"u8)
|| name.SequenceEqual("ValueTask"u8) || name.SequenceEqual("ValueTask`1"u8))
{
return true;
}
}
return false;
}
}
}