Maszyna, wirtualna czy nie, potrzebuje modelu obliczeń, który opisuje sposób wykonywania na nim obliczeń. Z definicji, jak tylko wykonuje obliczenia, implementuje pewien model obliczeń. Pytanie brzmi zatem: jaki model wybrać dla naszej maszyny wirtualnej? Maszyny fizyczne są ograniczone przez to, co można skutecznie i wydajnie wykonać w sprzęcie. Ale, jak zauważasz, maszyny wirtualne nie mają takich ograniczeń, są definiowane w oprogramowaniu przy użyciu arbitralnie języków wysokiego poziomu.
W rzeczywistości istnieją maszyny wirtualne, które są opisane na wysokim poziomie. Nazywa się je językami programowania . Na przykład standard C poświęca większość swoich stron na zdefiniowanie modelu dla tak zwanej „maszyny abstrakcyjnej C”, która opisuje, jak zachowują się programy C, a przez rozszerzenie (reguła as-if), w jaki sposób zgodny kompilator C (lub interpreter) powinien się zachowywać.
Oczywiście zwykle nie nazywamy tego maszyną wirtualną. VM zwykle oznacza coś niższego poziomu, bliżej sprzętu, nieprzeznaczonego do bezpośredniego programowania, zaprojektowanego do wydajnego wykonywania. To odchylenie wyboru oznacza, że coś, co akceptuje kod kompozycyjny wysokiego poziomu (jak to, co opisujesz) nie będzie uważane za maszynę wirtualną, ponieważ wykonuje kod wysokiego poziomu.
Ale, aby przejść do sedna, oto kilka powodów, dla których maszynę wirtualną (jak w, czymś docelowym kompilatora bajtów) opiera się na rejestrze lub tym podobne. Urządzenia do układania i rejestrowania są niezwykle proste. Dla każdej instrukcji istnieje sekwencja instrukcji, niektóre stany i semantyka (funkcja Stan -> Stan). Bez złożonych redukcji drzew, bez pierwszeństwa operatora. Analiza, analiza i wykonywanie jest bardzo proste, ponieważ jest to minimalny język (cukier syntaktyczny jest kompilowany) i zaprojektowany do odczytu maszynowego, a nie ludzkiego.
Natomiast parsowanie nawet najprostszych języków podobnych do C jest dość trudne, a jego wykonanie wymaga nielokalnych analiz, takich jak sprawdzanie i propagowanie typów, rozwiązywanie przeciążeń, utrzymywanie tabeli symboli, rozwiązywanie identyfikatorów ciągów , przekształcanie tekstu liniowego w AST sterowaną pierwszeństwem , i tak dalej. Opiera się na koncepcjach, które są naturalne dla ludzi, ale muszą zostać starannie opracowane przez maszyny.
Na przykład kod bajtowy JVM jest emitowany przez javac
. Praktycznie nigdy nie musi być odczytywany ani zapisywany przez ludzi, więc naturalne jest, aby dostosować go do zużycia przez maszyny. Jeśli zoptymalizowany go dla ludzi, JVM byłoby po prostu na każdym starcie odczytać kodu, analizować je, analizować to, a następnie przekształcić go w pośrednim reprezentacji przypominający taki uproszczony model maszyny anyway . Równie dobrze może odciąć środkowego mężczyznę.