public void EmitAwaitOnCompletedDynamic(EmitContext ec, FieldExpr awaiter) { var critical = Module.PredefinedTypes.ICriticalNotifyCompletion; if (!critical.Define()) { throw new NotImplementedException(); } var temp_critical = new LocalTemporary(critical.TypeSpec); var label_critical = ec.DefineLabel(); var label_end = ec.DefineLabel(); // // Special path for dynamic awaiters // // var awaiter = this.$awaiter as ICriticalNotifyCompletion; // if (awaiter == null) { // var completion = (INotifyCompletion) this.$awaiter; // this.$builder.AwaitOnCompleted (ref completion, ref this); // } else { // this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this); // } // awaiter.Emit(ec); ec.Emit(OpCodes.Isinst, critical.TypeSpec); temp_critical.Store(ec); temp_critical.Emit(ec); ec.Emit(OpCodes.Brtrue_S, label_critical); var temp = new LocalTemporary(Module.PredefinedTypes.INotifyCompletion.TypeSpec); awaiter.Emit(ec); ec.Emit(OpCodes.Castclass, temp.Type); temp.Store(ec); EmitOnCompleted(ec, temp, false); temp.Release(ec); ec.Emit(OpCodes.Br_S, label_end); ec.MarkLabel(label_critical); EmitOnCompleted(ec, temp_critical, true); ec.MarkLabel(label_end); temp_critical.Release(ec); }
public Expression EmitContinuationInitialization(EmitContext ec) { // // When more than 1 awaiter has been used in the block we // introduce class scope field to cache continuation delegate // if (awaiters > 1) { if (continuation == null) { continuation = AddCompilerGeneratedField("$continuation", new TypeExpression(action, Location), true); continuation.Define(); } var fexpr = new FieldExpr(continuation, Location); fexpr.InstanceExpression = new CompilerGeneratedThis(CurrentType, Location); // // if ($continuation == null) // $continuation = new Action (MoveNext); // fexpr.Emit(ec); var skip_cont_init = ec.DefineLabel(); ec.Emit(OpCodes.Brtrue_S, skip_cont_init); ec.EmitThis(); EmitActionLoad(ec); ec.Emit(OpCodes.Stfld, continuation.Spec); ec.MarkLabel(skip_cont_init); return(fexpr); } // // Otherwise simply use temporary local variable // var field = LocalVariable.CreateCompilerGenerated(action, OriginalSourceBlock, Location); EmitActionLoad(ec); field.EmitAssign(ec); return(new LocalVariableReference(field, Location)); }