質問

私はプログラムの実行中に実際の違いを理解しようとしています 解釈とスレッドの解釈をデコードして派遣します.

両方の例は本当に役立ちます。

Java Bytecodeの仕組みと、アセンブリ言語の仕組みを理解しています。しかし、DDIとTIはどこに適合しますか?

コンテクスト: 仮想マシン:システムとプロセス用の汎用性の高いプラットフォーム

役に立ちましたか?

解決

(注:「デコードとディスパッチ」とは、スイッチベースのインタープリターを意味すると仮定します。)

実行時にスイッチベースとスレッドインタープリターの違いは、基本的に、実行されるジャンプの数です。

スイッチベースのインタープリターでは、命令は中央の場所でデコードされ、デコードの結果に基づいて、デコードされた命令を処理するコードの一部にジャンプが実行されます。そのコードが命令の解釈が完了したら、それは集中解除コードに戻り、次の命令が進みます。これは、(少なくとも)解釈された命令ごとに2つのジャンプが実行されることを意味します。次の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 */
}

ジャンプを保存することとは別に、このようなスレッド通訳者は、複製された間接的なジャンプ(次の命令まで)が最新のCPUによってより良く予測できるため、より効率的です。 Anton Ertlにはいくつかの興味深い論文があります 彼のホームページ, 、特に「効率的な通訳者の構造とパフォーマンス」と呼ばれるもので、上記のコードが適応されました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top