Bytecode - Bytecode

Bytecode , auch als P-Code bezeichnet , ist eine Form von Befehlssatz, der für eine effiziente Ausführung durch einen Software- Interpreter entwickelt wurde . Im Gegensatz zu menschenlesbarem Quellcode sind Bytecodes kompakte numerische Codes, Konstanten und Referenzen (normalerweise numerische Adressen), die das Ergebnis des Compiler- Parsings und der semantischen Analyse von Dingen wie Typ, Geltungsbereich und Verschachtelungstiefe von Programmobjekten codieren .

Der Name Bytecode stammt von Befehlssätzen mit Ein- Byte- Opcodes gefolgt von optionalen Parametern. Zwischendarstellungen wie Bytecode können von Programmiersprachenimplementierungen ausgegeben werden , um die Interpretation zu erleichtern , oder sie können verwendet werden, um die Hardware- und Betriebssystemabhängigkeit zu reduzieren , indem derselbe Code plattformübergreifend auf verschiedenen Geräten ausgeführt werden kann. Bytecode kann oft entweder direkt auf einer virtuellen Maschine (einer P-Code-Maschine, dh einem Interpreter) ausgeführt werden oder kann für eine bessere Leistung weiter in Maschinencode kompiliert werden .

Da Bytecode-Befehle durch Software verarbeitet werden, können sie beliebig komplex sein, ähneln aber dennoch oft traditionellen Hardware-Befehlen: virtuelle Stapelmaschinen sind am gebräuchlichsten, aber virtuelle Registermaschinen wurden auch gebaut. Verschiedene Teile können oft in separaten Dateien gespeichert werden, ähnlich wie bei Objektmodulen , aber während der Ausführung dynamisch geladen.

Ausführung

Ein Bytecode-Programm kann ausgeführt werden, indem die Anweisungen einzeln analysiert und direkt ausgeführt werden. Diese Art von Bytecode-Interpreter ist sehr portabel. Einige Systeme, die als dynamische Übersetzer oder Just-in-Time- Compiler (JIT) bezeichnet werden, übersetzen Bytecode nach Bedarf zur Laufzeit in Maschinencode . Dies macht die virtuelle Maschine hardwarespezifisch, verliert jedoch nicht die Portabilität des Bytecodes. Beispielsweise wird Java- und Smalltalk- Code typischerweise im Bytecode-Format gespeichert, das dann typischerweise JIT-kompiliert wird, um den Bytecode vor der Ausführung in Maschinencode zu übersetzen. Dies führt zu einer Verzögerung, bevor ein Programm ausgeführt wird, wenn der Bytecode in nativen Maschinencode kompiliert wird, verbessert jedoch die Ausführungsgeschwindigkeit im Vergleich zur direkten Interpretation des Quellcodes erheblich, normalerweise um eine Größenordnung (10x).

Aufgrund des Leistungsvorteils führen viele Sprachimplementierungen heute ein Programm in zwei Phasen aus, wobei zuerst der Quellcode in Bytecode kompiliert und dann der Bytecode an die virtuelle Maschine übergeben wird. Es gibt Bytecode-basierte virtuelle Maschinen dieser Art für Java , Raku , Python , PHP , Tcl , mawk und Forth (Forth wird jedoch selten auf diese Weise über Bytecodes kompiliert, und seine virtuelle Maschine ist stattdessen allgemeiner). Die Implementierung von Perl und Ruby 1.8 funktioniert stattdessen durch eine abstrakte Syntaxbaumdarstellung, die aus dem Quellcode abgeleitet wird.

In jüngerer Zeit haben die Autoren von V8 und Dart die Vorstellung in Frage gestellt, dass für eine schnelle und effiziente VM-Implementierung Zwischenbytecode benötigt wird. Beide dieser Sprachimplementierungen führen derzeit eine direkte JIT-Kompilierung vom Quellcode zum Maschinencode ohne Bytecode-Vermittler durch.

Beispiele

Kompilierter Code kann mit einem integrierten Tool zum Debuggen des Low-Level-Bytecodes analysiert und untersucht werden. Das Tool kann von der Shell aus initialisiert werden, zum Beispiel:

>>> import dis # "dis" - Disassembler of Python byte code into mnemonics.
>>> dis.dis('print("Hello, World!")')
  1           0 LOAD_NAME                0 (print)
              2 LOAD_CONST               0 ('Hello, World!')
              4 CALL_FUNCTION            1
              6 RETURN_VALUE

Siehe auch

Anmerkungen

Verweise