DisassemblyDiagnoser does not show asm of called delegate
Here is simplified benchmark on .NET Core, but I have similar results on Full CLR:
[DisassemblyDiagnoser(recursiveDepth: 100)]
public class CallDelegate
{
private static readonly Func<string> _showTime = () => "Now is: " + DateTime.Now;
[Benchmark(Baseline = true)]
public object Direct() => "Now is: " + DateTime.Now;
[Benchmark]
public object CallFunc() => _showTime();
}
Here is the results:

Here is the asm CallDelegate_CallFunc_DefaultJob-asm.raw.html
00007ffb`7f260e10 FastExpressionCompiler.Benchmarks.Program+CallDelegate.CallFunc()
00007ffb`7f260e14 48b928162d7ffb7f0000 mov rcx,7FFB7F2D1628h
00007ffb`7f260e1e ba2d000000 mov edx,2Dh
00007ffb`7f260e23 e82846ad5f call coreclr!MetaDataGetDispenser+0x73970 (00007ffb`ded35450) not managed method
00007ffb`7f260e28 48b9586d45725e020000 mov rcx,25E72456D58h
00007ffb`7f260e32 488b01 mov rax,qword ptr [rcx]
00007ffb`7f260e35 488b4808 mov rcx,qword ptr [rax+8]
00007ffb`7f260e39 488b4018 mov rax,qword ptr [rax+18h]
The asm for Direct benchmark is a very long (recursiveDepth: 100)
BTW, My original benchmark target was https://github.com/dadhi/FastExpressionCompiler/blob/master/test/FastExpressionCompiler.Benchmarks/SimpleExpr_ParamPlusParam.cs
I've taken a look at this today and I don't have any good news.
With the most recent changes, the following benchmark for .NET Core 2.1:
public class CallDelegate
{
private static readonly Func<string> _showTime = () => "Now is: " + DateTime.Now;
[Benchmark]
public object CallFunc() => _showTime();
}
disassembles to:
## .NET Core 2.1.14 (CoreCLR 4.6.28207.04, CoreFX 4.6.28208.01), X64 RyuJIT
```assembly
; BenchmarkDotNet.Samples.CallDelegate.CallFunc()
sub rsp,28
mov rcx,7FF8472B4FF0
mov edx,16
call CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
mov rcx,13CEDAF74F8
mov rax,[rcx]
lea rcx,[rax+8]
mov rcx,[rcx]
mov rax,[rax+18]
add rsp,28
jmp rax
; Total bytes of code 55
In IL the call to a delegate is represented as a virtual call which is the most indirect call we can get ;/:
.method public hidebysig
instance object CallFunc () cil managed
{
.custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.BenchmarkAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2187
// Code size 11 (0xb)
.maxstack 8
// return _showTime();
IL_0000: ldsfld class [System.Runtime]System.Func`1<string> TryNewDisassembler.CallDelegate::_showTime
IL_0005: callvirt instance !0 class [System.Runtime]System.Func`1<string>::Invoke()
// (no C# code)
IL_000a: ret
} // end of method CallDelegate::CallFunc
@0xd4d @leculver do you have any suggestions about how we could disassemble the delegate calls?
@janvorli do you have any suggestion for disassembling delegate calls? Sample:
.NET 6.0.9 (6.0.922.41905), X64 RyuJIT AVX2
; BenchmarkDotNet.Samples.CallDelegate.CallFunc()
push rbp
sub rsp,30
lea rbp,[rsp+30]
xor eax,eax
mov [rbp-8],rax
mov [rbp+10],rcx
mov rcx,7FFAA1F42258
mov edx,50
call CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
mov rcx,1A118007330
mov rcx,[rcx]
mov [rbp-8],rcx
mov rcx,[rbp-8]
mov rcx,[rcx+8]
mov rax,[rbp-8]
call qword ptr [rax+18]
nop
add rsp,30
pop rbp
ret
; Total bytes of code 79