DeCode и отправка интерпретация против резьбовых интерпретаций

StackOverflow https://stackoverflow.com/questions/3848343

Вопрос

Я пытаюсь понять практическую разницу во время выполнения программы в Декодирование и рассылка интерпретации и резьбовое интерпретация.

Пример обоих действительно поможет.

Я понимаю, как работает Java Bytecode и как работает языком сборки. Но где DDI и Ti вписываются?

Контекст: Виртуальные машины: универсальные платформы для систем и процессов

Это было полезно?

Решение

(Примечание. Я предположим, что по «декодированию и отправке» вы имеете в виду переводчик на основе коммутатора.)

Разница между выключателем и резьбовым интерпретатором во время выполнения, в основном, количество проведенных прыжков.

В интерпретатере на основе коммутатора инструкции декодируются в каком-либо центральном расположении, и на основе результата декодирования скачок проводится на кусок кода, который обрабатывает декодированную инструкцию. Как только этот кусок кода завершил интерпретацию инструкции, он переходит обратно в централизованный код декодирования, который выходит с следующей инструкцией. Это означает, что (по крайней мере) два прыжка выполняются на интерпретацию инструкции. Следующий кусок C-кода C иллюстрирует то, что может выглядеть такой переводчик:

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 */
    }
  }
}

В резьбовом интерпретатере код декодирования не централизован, а скорее дублирован в конце каждого куска кода, который обрабатывает инструкцию. Это означает, что после интерпретации инструкции вместо того, чтобы перейти назад к некоторому централизованному коду декодирования, интерпретатор декодирует следующую инструкцию и немедленно переходит к нему. Реализация резьбового кода эффективно в ANSI-C на самом деле невозможно, но расширение GCC «Computed Goto» очень хорошо работает для этого. Вот резьбовая версия предыдущего интерпретатора:

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 */
}

Помимо спасения прыжка, такие резьбовые переводчики также более эффективны, потому что реплицированный косвенный прыжок (к следующей инструкции) может быть прогнозирован лучше современными процессорами. У Anton Ertl есть некоторые интересные документы на его домашняя страница, Особенно тот, который называется «структурой и производительность эффективных переводчиков», из которых были адаптированы вышеуказанные кусочки кода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top