Ich werde das Kompilieren von IL-Code in native CPU-Anweisungen anhand des folgenden Beispiels beschreiben.
public class Example
{
static void Main()
{
Console.WriteLine("Hey IL!!!");
}
}
In erster Linie kennt CLR alle Details über den Typ und welche Methode von diesem Typ aufgerufen wird, was auf Metadaten zurückzuführen ist.
Wenn die CLR beginnt, IL in der nativen CPU-Anweisung auszuführen, weist die CLR zu diesem Zeitpunkt interne Datenstrukturen für jeden Typ zu, auf den der Main-Code verweist.
In unserem Fall haben wir nur einen Typ Konsole, daher ordnet CLR über diese interne Struktur eine interne Datenstruktur zu, und wir verwalten den Zugriff auf die referenzierten Typen
Innerhalb dieser Datenstruktur enthält CLR Einträge zu allen von diesem Typ definierten Methoden. Jeder Eintrag enthält die Adresse, an der sich die Implementierung der Methode befindet.
Bei der Initialisierung dieser Struktur setzt CLR jeden Eintrag in undokumentierte FUNCTION, die in CLR selbst enthalten ist. Und wie Sie sich vorstellen können, wird diese FUNCTION als JIT-Compiler bezeichnet.
Insgesamt können Sie JIT Compiler als CLR-Funktion betrachten, die IL in native CPU-Anweisungen kompiliert. Lassen Sie mich Ihnen im Detail zeigen, wie dieser Prozess in unserem Beispiel ablaufen wird.
1.Wenn Main's WriteLine zum ersten Mal aufruft, wird die JITCompiler-Funktion aufgerufen.
2. Die JIT-Compilerfunktion weiß, welche Methode aufgerufen wird und welcher Typ diese Methode definiert.
3.Dann durchsucht der Jit Compiler die Assembly, in der dieser Typ definiert wurde, und ruft den IL-Code für die von diesem Typ definierte Methode ab, in unserem Fall den IL-Code der WriteLine-Methode.
4.JIT-Compiler ordnen DYNAMIC- Speicherblock zu, danach überprüft und kompiliert JIT IL-Code in nativen CPU-Code und speichert diesen CPU-Code in diesem Speicherblock.
5.Dann kehrt der JIT-Compiler zum internen Datenstruktureintrag zurück und ersetzt die Adresse (die sich hauptsächlich auf die IL-Code-Implementierung von WriteLine bezieht) durch einen neuen dynamisch erstellten Speicherblock, der native CPU-Anweisungen von WriteLine enthält.
6. Schließlich springt die JIT-Compiler-Funktion zum Code im Speicherblock. Dieser Code ist die Implementierung der WriteLine-Methode.
7.Nach der Implementierung der WriteLine kehrt der Code zum Hauptcode zurück, der die Ausführung wie gewohnt fortsetzt.