Frage

Ich versuche, den praktischen Unterschied während der Ausführung eines Programms in Decode und Versand Interpretation und Threaded Interpretation zu verstehen, .

Beispiel für beide wird wirklich helfen.

Ich verstehe, wie Java-Bytecode funktioniert und wie eine Assembler-Sprache funktioniert. Aber woher kommt DDI und TI passen?

Kontext: Virtuelle Maschinen: vielseitig Plattformen für Systeme und Prozesse

War es hilfreich?

Lösung

. (Anmerkung: Ich werde davon ausgehen, dass durch "decode und Versand" bedeuten Sie einen Switch-basierten Interpreter)

Der Unterschied zwischen einem Schalter-basierten und einem Gewinde Interpreter zur Laufzeit ist im Grunde die Anzahl der Sprünge, die ausgeführt werden.

In einem switchbasierten Interpreter werden Befehle zu irgendein zentralen Lage decodiert und basierend auf dem Ergebnis der Decodierung wird ein Sprung zu dem Stück Code ausgeführt wird, dass der decodierte Befehl Griffe. Sobald das Stück des Codes beendet hat die Anweisung interpretiert, springt er zurück zu dem zentralisierten Dekodieren Code, der mit dem nächsten Befehl fort. Dies bedeutet, dass (mindestens) zwei Sprünge pro interpretierten Anweisung durchgeführt werden. Das folgende Stück C-Code zeigt, was ein solcher Interpreter aussehen könnte:

typedef enum {
  add, /* ... */
} instruction_t;

void interpret() {
  static instruction_t program[] = { add /* ... */ };
  instruction_t* pc = program;
  int* sp = ...; /* stack pointer */
  for (;;) {
    switch (*pc++) {
      case add:
        sp[1] += sp[0];
        sp++;
        break;
        /* ... other instructions */
    }
  }
}

In einem Gewinde Interpreter, der Decodierung Code nicht zentralisiert, sondern am Ende jedes Stück Code dupliziert, dass Griffe eine Anweisung. Dies bedeutet, dass, sobald ein Befehl interpretiert wurde, anstelle die zurück zu einem gewissen zentralisierten Dekodieren Code springt, der Interpreter die nächste Anweisung decodiert und springt sofort zu. Gewinde Code Implementieren effizient in ANSI-C ist nicht wirklich möglich, aber GCC „computed goto“ Erweiterung funktioniert sehr gut dafür. Hier ist eine Gewinde Version des vorherigen Interpreter:

void interpret() {
  void* program[] = { &&l_add, /* ... */ };
  int* sp = ...;
  void** pc = program;
  goto **pc; /* jump to first instruction */
 l_add:
  sp[1] += sp[0];
  ++sp;
  goto **(++pc); /* jump to next instruction */
  /* ... other instructions */
}

Neben Speichern einen Sprung, wie Gewinde Dolmetscher sind auch effizienter, da der replizierte indirekte Sprung (auf den nächsten Befehl) durch modernen CPUs besser vorhergesagt werden. Anton Ertl hat einige interessante Papiere auf seiner Homepage , besonders die genannt „Die Struktur und Leistung von Efficient Interpreter“, aus dem die obigen Teile des Codes angepasst wurden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top