@@ -60,16 +60,16 @@ public override MethodIL EmitIL()
6060 }
6161 }
6262
63- if ( Context . Target . Architecture != TargetArchitecture . X86 )
63+ if ( _targetMethod . RequiresInstArg ( ) )
6464 {
65- if ( _targetMethod . RequiresInstArg ( ) )
66- {
67- ilStream . EmitLdc ( 0 ) ;
68- ilStream . Emit ( ILOpcode . conv_i ) ;
69- }
70- ilStream . EmitLdArg ( 0 ) ;
65+ ilStream . EmitLdc ( 0 ) ;
66+ ilStream . Emit ( ILOpcode . conv_i ) ;
67+ ilStream . Emit ( ILOpcode . call , ilEmitter . NewToken ( Context . GetCoreLibEntryPoint ( "System.Runtime.CompilerServices"u8 , "RuntimeHelpers"u8 , "SetNextCallGenericContext"u8 , null ) ) ) ;
7168 }
7269
70+ ilStream . EmitLdArg ( 0 ) ;
71+ ilStream . Emit ( ILOpcode . call , ilEmitter . NewToken ( Context . GetCoreLibEntryPoint ( "System.Runtime.CompilerServices"u8 , "RuntimeHelpers"u8 , "SetNextCallAsyncContinuation"u8 , null ) ) ) ;
72+
7373 foreach ( var param in _targetMethod . Signature )
7474 {
7575 var local = ilEmitter . NewLocal ( param ) ;
@@ -78,24 +78,13 @@ public override MethodIL EmitIL()
7878 ilStream . EmitLdLoc ( local ) ;
7979 }
8080
81- if ( Context . Target . Architecture == TargetArchitecture . X86 )
82- {
83- ilStream . EmitLdArg ( 0 ) ;
84- if ( _targetMethod . RequiresInstArg ( ) )
85- {
86- ilStream . EmitLdc ( 0 ) ;
87- ilStream . Emit ( ILOpcode . conv_i ) ;
88- }
89- }
81+ ilStream . Emit ( ILOpcode . call , ilEmitter . NewToken ( _targetMethod ) ) ;
9082
91- MethodDesc resumingMethod = new ExplicitContinuationAsyncMethod ( _targetMethod ) ;
92- ilStream . Emit ( ILOpcode . call , ilEmitter . NewToken ( resumingMethod ) ) ;
93-
94- bool returnsVoid = resumingMethod . Signature . ReturnType . IsVoid ;
83+ bool returnsVoid = _targetMethod . Signature . ReturnType . IsVoid ;
9584 ILLocalVariable resultLocal = default ;
9685 if ( ! returnsVoid )
9786 {
98- resultLocal = ilEmitter . NewLocal ( resumingMethod . Signature . ReturnType ) ;
87+ resultLocal = ilEmitter . NewLocal ( _targetMethod . Signature . ReturnType ) ;
9988 ilStream . EmitStLoc ( resultLocal ) ;
10089 }
10190
@@ -113,7 +102,7 @@ public override MethodIL EmitIL()
113102 ilStream . Emit ( ILOpcode . brtrue , doneResult ) ;
114103 ilStream . EmitLdArg ( 1 ) ;
115104 ilStream . EmitLdLoc ( resultLocal ) ;
116- ilStream . Emit ( ILOpcode . stobj , ilEmitter . NewToken ( resumingMethod . Signature . ReturnType ) ) ;
105+ ilStream . Emit ( ILOpcode . stobj , ilEmitter . NewToken ( _targetMethod . Signature . ReturnType ) ) ;
117106 ilStream . EmitLabel ( doneResult ) ;
118107 }
119108 ilStream . EmitLdLoc ( newContinuationLocal ) ;
@@ -122,135 +111,4 @@ public override MethodIL EmitIL()
122111 return ilEmitter . Link ( this ) ;
123112 }
124113 }
125-
126- /// <summary>
127- /// A dummy method used to tell the jit that we want to explicitly pass the hidden Continuation parameter
128- /// as well as the generic context parameter (if any) for async resumption methods.
129- /// This method should be marked IsAsync=false and HasInstantiation=false. These are defaults
130- /// for MethodDesc and so aren't explicitly set in the code below.
131- /// </summary>
132- internal sealed partial class ExplicitContinuationAsyncMethod : MethodDesc
133- {
134- private MethodSignature _signature ;
135- private readonly MethodDesc _wrappedMethod ;
136- private readonly MethodDesc _typicalDefinition ;
137-
138- public ExplicitContinuationAsyncMethod ( MethodDesc target )
139- {
140- _wrappedMethod = target ;
141-
142- MethodDesc targetTypicalDefinition = target . GetTypicalMethodDefinition ( ) ;
143- if ( targetTypicalDefinition != target )
144- _typicalDefinition = new ExplicitContinuationAsyncMethod ( targetTypicalDefinition ) ;
145- else
146- _typicalDefinition = this ;
147- }
148-
149- public MethodDesc Target => _wrappedMethod ;
150-
151- /// <summary>
152- /// To explicitly pass the hidden parameters for async resumption methods,
153- /// we need to add explicit Continuation and generic context parameters to the signature.
154- /// </summary>
155- private MethodSignature InitializeSignature ( )
156- {
157- // Async methods have an implicit Continuation parameter
158- // The order of parameters depends on the architecture
159- // non-x86: this?, genericCtx?, continuation, params...
160- // x86: this?, params, continuation, genericCtx?
161- // To make the jit pass arguments in this order, we can add the continuation parameter
162- // at the end for x86 and at the beginning for other architectures.
163- // The 'this' parameter and generic context parameter (if any) can be handled by the jit.
164-
165- var parameters = new TypeDesc [ _wrappedMethod . Signature . Length + 1 + ( _wrappedMethod . RequiresInstArg ( ) ? 1 : 0 ) ] ;
166-
167- TypeDesc continuation = Context . SystemModule . GetKnownType ( "System.Runtime.CompilerServices"u8 , "Continuation"u8 ) ;
168- if ( Context . Target . Architecture == TargetArchitecture . X86 )
169- {
170- int i = 0 ;
171- for ( ; i < _wrappedMethod . Signature . Length ; i ++ )
172- {
173- parameters [ i ] = _wrappedMethod . Signature [ i ] ;
174- }
175- parameters [ i ++ ] = continuation ;
176- if ( _wrappedMethod . RequiresInstArg ( ) )
177- {
178- parameters [ i ] = Context . GetWellKnownType ( WellKnownType . Void ) . MakePointerType ( ) ;
179- }
180- }
181- else
182- {
183- int i = 0 ;
184- if ( _wrappedMethod . RequiresInstArg ( ) )
185- {
186- parameters [ i ++ ] = Context . GetWellKnownType ( WellKnownType . Void ) . MakePointerType ( ) ;
187- }
188- parameters [ i ++ ] = continuation ;
189- foreach ( var param in _wrappedMethod . Signature )
190- {
191- parameters [ i ++ ] = param ;
192- }
193- }
194- // Get the return type from the Task-returning variant
195- TypeDesc returnType ;
196- if ( _wrappedMethod is AsyncMethodVariant variant )
197- {
198- Debug . Assert ( variant . Target . Signature . ReturnsTaskOrValueTask ( ) ) ;
199- if ( variant . Target . Signature . ReturnType is { HasInstantiation : true } wrappedReturnType )
200- {
201- returnType = wrappedReturnType . Instantiation [ 0 ] ;
202- }
203- else
204- {
205- returnType = Context . GetWellKnownType ( WellKnownType . Void ) ;
206- }
207- }
208- else
209- {
210- // AsyncExplicitImpl
211- returnType = _wrappedMethod . Signature . ReturnType ;
212- }
213-
214- return _signature = new MethodSignature (
215- _wrappedMethod . Signature . Flags ,
216- 0 ,
217- returnType ,
218- parameters ) ;
219- }
220-
221- public override bool HasCustomAttribute ( string attributeNamespace , string attributeName ) => throw new NotImplementedException ( ) ;
222-
223- public override MethodSignature Signature
224- {
225- get
226- {
227- if ( _signature is null )
228- return InitializeSignature ( ) ;
229-
230- return _signature ;
231- }
232- }
233-
234- public override string DiagnosticName => $ "ExplicitContinuationAsyncMethod({ _wrappedMethod . DiagnosticName } )";
235-
236- public override TypeDesc OwningType => _wrappedMethod . OwningType ;
237-
238- public override TypeSystemContext Context => _wrappedMethod . Context ;
239-
240- public override bool IsInternalCall => true ;
241-
242- public override MethodDesc GetTypicalMethodDefinition ( ) => _typicalDefinition ;
243- }
244-
245- public static class AsyncResumptionStubExtensions
246- {
247- public static bool IsExplicitContinuationAsyncMethod ( this MethodDesc method )
248- {
249- return method is ExplicitContinuationAsyncMethod ;
250- }
251- public static MethodDesc GetExplicitContinuationAsyncMethodTarget ( this MethodDesc method )
252- {
253- return ( ( ExplicitContinuationAsyncMethod ) method ) . Target ;
254- }
255- }
256114}
0 commit comments