From C# to CLR Jitted Code – Call Delegate



How expensive is a delegate call vs a direct function call? The delegate call is actually pretty fast. The delegate typically stores the function and the calling target. When we invoke the delegate, the JIT will retrieve the function pointer and the target and complete the call. You can see from below example.


Here is the C# code


    public class CallDelegate


    {


        [MethodImpl(MethodImplOptions.NoInlining)]


        public static void Run()


        {


            Foo();          


            RetVoid f1 = new RetVoid(Foo);


            f1();           /// Delegate invoke


        }


 


        [MethodImpl(MethodImplOptions.NoInlining)]


        public static void Foo()


        {


            Console.WriteLine(“foo”);


        }


}


 


   L_0000: nop


    L_0001: call void JitBlog.CallDelegate::Foo()


    L_0006: nop


    L_0007: ldnull


    L_0008: ldftn void JitBlog.CallDelegate::Foo()


    L_000e: newobj instance void JitBlog.RetVoid::.ctor(object, native int)       // Build the delegate objiect


    L_0013: stloc.0


    L_0014: ldloc.0


    L_0015: callvirt instance void JitBlog.RetVoid::Invoke()   // Delegate invoke


    L_001a: nop


L_001b: ret


 


 Here is the disassmbly


 


            call    [CallDelegate.Foo()]


            nop


            mov     ECX, 0x1f336c8                 //Type of delegate


            call    CORINFO_HELP_NEWSFAST_CHKRESTORE


            mov     ESI, EAX


            mov     EAX, 0x1f3c090


            push    EAX


            push    0x4220f8       // Delegate stub


            mov     ECX, ESI


            xor     EDX, EDX


            call    MulticastDelegate.CtorOpened(ref,int,int)


            nop


            mov     EDI, ESI


            mov     ECX, EDI


            mov     EAX, dword ptr [ECX+12]      // Retrieve the function pointer from the Delegate


            mov     ECX, gword ptr [ECX+4]       // Retrieve the target object address from the target


            call    EAX                                          // complete the call


 


Comments (0)