Hallo Leute!
Haben Sie eine sehr einfache App, die eine solche Schnittstellenmethode aufruft.
namespace InterfaceCalls
{
public interface IFoo
{
int Bar();
}
class Program
{
public static int M1(IFoo foo)
{
return foo.Bar();
}
static void Main(string[] args)
{
M1(null);
}
}
}
Das erzeugt das folgende ASM für 2.2 (für 3.0 gibt es lea rsp,[rbp] statt add rsp,30h)
return foo.Bar();
00007FFE7B521846 mov rcx,rsi
00007FFE7B521849 mov r11,7FFE7B410028h
00007FFE7B521853 cmp dword ptr [rcx],ecx
00007FFE7B521855 call qword ptr [7FFE7B410028h]
00007FFE7B52185B nop
00007FFE7B52185C add rsp,30h
00007FFE7B521860 pop rsi
00007FFE7B521861 ret
Entschuldigung für möglicherweise sehr dumme und unerfahrene Fragen :) aber könnte mir bitte jemand einen Hinweis geben zu:
1 Warum brauchen wir hier die cmp-Anweisung (es gibt keinen bedingten Sprung nach dem cmp)
2 Was ist 7FFE7B410028h und warum wir hier r11 laden
3 Ist es nicht zu teuer, cmp pro Schnittstellenaufruf zu haben (könnte cml in diesem Fall zu einem Misserfolg der Verzweigungsvorhersage führen?)
Vielen Dank!
Der cmp ist ein früher Null-Check.
Informationen zum Schnittstellenversand finden Sie hier https://github.com/dotnet/coreclr/blob/master/Documentation/botr/virtual-stub-dispatch.md
Warum brauchen wir hier die cmp-Anweisung (es gibt keinen bedingten Sprung nach dem cmp)
Um ein NullReferenceException
an dem Punkt des Anrufs auszulösen, wenn this
null
.
Was ist 7FFE7B410028h und warum laden wir hier in r11?
Die Adresse einer "Indirektionszelle", die auf einen Stub zeigt, der die Schnittstellenimplementierungsmethode auflöst und aufruft. Leider ist das Auflösen von Schnittstellenmethoden ein relativ komplizierter Vorgang, der nicht "inline" durchgeführt werden kann.
Es zeigt zunächst auf https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/coreclr/src/vm/amd64/VirtualCallStubAMD64.asm#L28
Einige Dokumentation ist hier verfügbar (obwohl ich nicht sicher bin, wie aktuell sie ist)
https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md
Sie können wahrscheinlich direkt zu https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md#stubs springen , um einen schnellen Überblick zu erhalten.
Ist es nicht zu teuer, cmp pro Schnittstellenaufruf zu haben (könnte cml in diesem Fall zu einem Fehlschlag der Verzweigungsvorhersage führen?)
Es ist ein Vergleichsbefehl, kein bedingter Verzweigungsbefehl, also hat er nichts mit der Verzweigungsvorhersage zu tun. Und es ist sehr günstig im Vergleich zu den tatsächlichen Kosten für Schnittstellenanrufe.
@mikedn @omariom Danke
Hilfreichster Kommentar
Um ein
NullReferenceException
an dem Punkt des Anrufs auszulösen, wennthis
null
.Die Adresse einer "Indirektionszelle", die auf einen Stub zeigt, der die Schnittstellenimplementierungsmethode auflöst und aufruft. Leider ist das Auflösen von Schnittstellenmethoden ein relativ komplizierter Vorgang, der nicht "inline" durchgeführt werden kann.
Es zeigt zunächst auf https://github.com/dotnet/runtime/blob/4f9ae42d861fcb4be2fcd5d3d55d5f227d30e723/src/coreclr/src/vm/amd64/VirtualCallStubAMD64.asm#L28
Einige Dokumentation ist hier verfügbar (obwohl ich nicht sicher bin, wie aktuell sie ist)
https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md
Sie können wahrscheinlich direkt zu https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/virtual-stub-dispatch.md#stubs springen , um einen schnellen Überblick zu erhalten.
Es ist ein Vergleichsbefehl, kein bedingter Verzweigungsbefehl, also hat er nichts mit der Verzweigungsvorhersage zu tun. Und es ist sehr günstig im Vergleich zu den tatsächlichen Kosten für Schnittstellenanrufe.