Parrot

Eine VM für mehrere Skriptsprachen

Bytecode

Einführung

Parrot befindet sich noch in der Entwicklung. Es ist sehr wahrscheinlich, dass sich das endgültige Format des Parrot Bytecodes sich von diesem unterscheidet.

Eine Bytecodedatei hat einen Header und beliebig viele Segmente. Alle Segmentgrenzen sind an einem vielfachen von 16 ausgerichtet um theoretisch eine Wortbreite von 128 Bit optimal zu unterstützen.

Eine Besonderheit des Parrot Bytecode ist, dass zum Beispiel die Byte-Ordnung, Wortgröße oder das Format von Fleißkommazahlen nicht fix sind. Der Bytecode ist trozdem portabel, da der BytecodeLoader dafür zuständig ist, alle Formate On-The-Fly auf das Zielsystem zu konvertieren.

Header


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 0      | 0xFE 0x50 0x42 0x43 0x0D 0x0A 0x1A 0x0A                |
|        | Parrot "Magic String"                                  |
+--------+--------------------------------------------------------+
| 8      | Wortgröße in Bytes                                     |
|        |   0x04 - 4 byte (32 Bit)                               |
|        |   0x08 - 8 byte (64 Bit)                               |
+--------+--------------------------------------------------------+
| 9      | Byte Ordnung                                           |
|        |   0x00 - Little Endian                                 |
|        |   0x01 - Big Endian                                    |
+--------+--------------------------------------------------------+
| 10     | Kodierung der Gleitkommazahlen                         |
|        |   0x00 - IEEE 754 8 Byte double                        |
|        |   0x01 - i386 Little Endian 12 Byte long double        |
+--------+--------------------------------------------------------+
| 11     | „Major“ Versionsummer von Parrot                       |
+--------+--------------------------------------------------------+
| 12     | „Minor“ Versionsummer von Parrot                       |
+--------+--------------------------------------------------------+
| 13     | „Patch“ Versionsummer von Parrot                       |
+--------+--------------------------------------------------------+
| 14     | „Major“ Bytecode-Format-Versionsnummer                 |
+--------+--------------------------------------------------------+
| 14     | „Minor“ Bytecode-Format-Versionsnummer                 |
+--------+--------------------------------------------------------+
| 16     | Typ der UUID dieser Bytecodedatei                      |
|        |   0x00 - Keine UUID                                    |
|        |   0x01 - MD5                                           |
+--------+--------------------------------------------------------+
| 17     | Länge der UUID. Maximal 255.                           |
+--------+--------------------------------------------------------+
| 18     | UUID mit einer, in Byte 17 angegebenen, Länge.         |
+--------+--------------------------------------------------------+
| 18 + n | Mit 0 gefüllter Überhang, um aus der Header-Größe ein  |
|        | Vielfaches von 16 zu machen.                           |
+--------+--------------------------------------------------------+

Segmente

Nach dem Header folgt der eigentliche Inhalt, welcher in verschiedene Segmente unterteilt ist.

Jede Bytecode-Datei hat ein "Directory", in welchem alle Segmente aufgelistet sind. Es ist geplant, dass es später verschiedene Formate eines solchen Verzeichnes geben kann. Die Art des Formates wird durch folgenden Header bestimmt. Auf diesen Header muss das Directory-Segment folgen.


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 0      | Verzeichnisformat                                      |
|        |    0x01 - Directory Format 1                           |
+--------+--------------------------------------------------------+
| 1      | 0x00 0x00 0x00 - Reserviert                            |
+--------+--------------------------------------------------------+

Jedes Segment hat einen eigenen Header, in welchem beschrieben ist, aus wie vielen Operationscodes das Segment besteht.


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 0      | Anzahl der Opcodes im Segment                          |
+--------+--------------------------------------------------------+

Directory Segment

Als erstes ist die Anzahl der Verzeichniseinträge angegeben.


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 1      | Anzahl der Einträge im Verzeichnis.                    |
+--------+--------------------------------------------------------+

Danach folgen die Verzeichniseinträge. Ein Verzeichniseintrag ist folgendermaßen aufgebaut:


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 1      | Segmenttyp                                             |
|        |   0x00 - Reserviert (Directory Segment)                |
|        |   0x01 - Default Segment                               |
|        |   0x02 - Fixup Segment                                 |
|        |   0x03 - Constant Table Segment                        |
|        |   0x04 - Bytecode Segment                              |
|        |   0x05 - Annotations Segment                           |
|        |   0x06 - PIC Data Segment                              |
|        |   0x07 - Dependencies Segment                          |
+--------+--------------------------------------------------------+
| 2      | Name des Segments als String                           |
+--------+--------------------------------------------------------+
| n + 1  | Offset zu den Segmentdaten                             |
+--------+--------------------------------------------------------+
| n + 2  | Länge des Segments                                     |
+--------+--------------------------------------------------------+

Bytecode Segment

In dem Bytecode-Segment ist der eigentliche Programmcode enthalten. Dieser besteht aus einem Operationscode in Wortlänge und beliebig vielen Operanden. Ein Operand kann ein Register oder eine Konstante sein.

Constants Segment

Wie bei dem Directory Segment ist zu erst die Anzahl angegeben.


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 1      | Anzahl der Konstanten                                  |
+--------+--------------------------------------------------------+

Danach folgt eine Liste von Konstanten. Ein Eintrag ist folgendermaßen aufgebaut:


+--------+--------------------------------------------------------+
| Byte   | Beschreibung                                           |
+--------+--------------------------------------------------------+
| 1      | Typ der Konstante                                      |
|        |   0x6E - Zahl (ASCII 'n')                              |
|        |   0x73 - Zeichenkette ('s')                            |
|        |   0x70 - PMC (ASCII 'p')                               |
+--------+--------------------------------------------------------+
| 2      | Daten                                                  |
+--------+--------------------------------------------------------+

Damit ein PMC als Konstante abgelegt werden kann, müssen die Methoden "freeze" and "thaw" überschrieben werden.

Erstellt von Johannes Barop