Ich las einen Beitrag auf Reddit auf Herb Stutter: JIT will never be as fast as native und jemand machte einen Kommentar, dass es unglaublich war, dass jemand Herb "falsch informiert", dass C# virtuelle Methoden anstelle von nicht virtuellen verwendet (Sie können den Artikel here lesen). Es brachte mich zum Nachdenken und ich machte ein kleines Programm und bemerkte, dass C# tatsächlich virtuelle Methoden für CIL (callvirt vs call) generiert. Aber dann wurde mir gesagt, dass es nicht so einfach ist und dass der JIT den Code einbinden kann, anstatt vtables und dynamischen Versand zu verwenden. Ich habe meinen Debugger hochgefahren und versucht zu sehen. Hier ist mein einfaches Programm:Wie man erkennt, ob ein Programm dynamischen Versand verwendet, indem man auf die Assembly schaut
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.TestIt();
t.TestOut();
}
}
class Test
{
public Test() { }
public void TestIt()
{
Console.WriteLine("TESTIT");
}
public void TestOut()
{
Console.WriteLine("TESTOUT");
}
}
}
Und dann hier ist die Montage:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test t = new Test();
00000000 push ebp
00000001 mov ebp,esp
00000003 push esi
00000004 mov ecx,439E68h
00000009 call FFCE0AD4
0000000e mov esi,eax
t.TestIt();
00000010 call 704BBEB8 // Call to Console.WriteLine()
00000015 mov ecx,eax
00000017 mov edx,dword ptr ds:[02A02088h]
0000001d mov eax,dword ptr [ecx]
0000001f call dword ptr [eax+000000D8h]
t.TestOut();
00000025 call 704BBEB8 // Call to Console.WriteLine()
0000002a mov ecx,eax
0000002c mov edx,dword ptr ds:[02A0208Ch]
00000032 mov eax,dword ptr [ecx]
00000034 call dword ptr [eax+000000D8h]
0000003a pop esi
}
0000003b pop ebp
0000003c ret
Meine Frage ist: durch in der Sammelstelle der Suche, wie man nicht sagen, ob es dynamische Dispatch verwendet? Meine Vermutung ist, dass es wegen dieser vier Befehle, die ähneln, was ich von meiner Programmiersprache Klasse erinnern:
0000002a mov ecx,eax
0000002c mov edx,dword ptr ds:[02A0208Ch]
00000032 mov eax,dword ptr [ecx]
00000034 call dword ptr [eax+000000D8h]
Bin ich richtig in der Annahme ist das dynamische Dispatch? Wenn ja, gibt es noch andere verräterische Zeichen? Wenn ich falsch liege, wie würde ich in der Lage sein zu sagen, ob es sich um dynamischen Versand handelt oder nicht?
So ist das Muster der Suche nach einem Offset ein Zeichen der dynamischen Versand oder ist es die ganze 4 Befehlsgruppe, die das Tell Tale Zeichen ist? – Jetti
@Jetti: Ich habe die Antwort bearbeitet. Das Vorzeichen des dynamischen Versands verwendet die Objektadresse, um die Funktionsadresse abzuleiten und dann diese Funktionsadresse zu verwenden, um den Aufruf auszuführen. – sharptooth
vielen Dank. Ich war zu 80% sicher, dass es so war, aber aufgrund meiner mangelnden Erfahrung wollte ich nur sicher sein. – Jetti