3

"バイトコードプログラムは通常、一度に1つの命令を解析することによって実行されます。この種のバイトコードインタープリタは非常に移植性がありますが、ダイナミックトランスレータまたはジャストインタイム(JIT)実行時にバイトコードを機械語に変換する必要があります。これにより、仮想マシンはポータブルになりません。バイトコードの解析された命令と機械語の違いは?

この段落についての質問があることである:バイトコードの後に​​処理されます、 解析された命令とマシン語(またはマシンコード)の違いは何ですか?

+0

"構文解析された命令"抽象構文木の表現に? – none

答えて

7

JITは、バイトコードインタープリタとは異なります。

は、次のC関数を考えてみましょう:

int sum() { 
    return 5 + 6; 
} 

これは、直接マシンコードをコンパイルされます。 x86とARMプロセッサの正確な指示は異なるでしょう。

私たちは、基本的なバイトコードインタプリタを書いた場合は、次のようになります。

for(;;) { 
    switch(*currentInstruction++) { 
    case OP_PUSHINT: 
     *stack++ = nextInt(currentInstruction); 
     break; 
    case OP_ADD: 
     --stack; 
     stack[-1].add(*stack); 
     break; 
    case OP_RETURN: 
     return stack[-1]; 
    } 
} 

これは、その後、次の命令のセットを解釈することができます:あなたはバイトコードインタプリタをコンパイルした場合

OP_PUSHINT (5) 
OP_PUSHINT (6) 
OP_ADD 
OP_RETURN 

をx86またはARMの両方であれば、インタプリタを書き直すことなく同じバイトコードを実行することができます。

あなたはバイトコードインタプリタは、プロセッサ固有の命令を発するようにC++コンパイラに依存しているのに対し、サポートされている各プロセッサのためのプロセッサ固有の命令(マシンコード)を放出する必要があるだろうJITコンパイラを書いた場合。

2

違いはありません.JITコンパイラは、ハードウェア上で実行されるマシンコードを生成します。

1

最終的にはすべてが機械の説明になっています。

  1. ネイティブアプリ - 直接実行されるマシン命令が含まれています。
  2. JITアプリケーションバイトコードがマシン命令にコンパイルされ、実行されます。
  3. 翻訳されたアプリケーションバイトコードは、ネイティブアプリケーションである仮想マシンによって変換されます。

#1では、オーバーヘッドが最も少なく、#3ではオーバーヘッドが最も大きくなります。したがって、パフォーマンスは#1では最速で、#2では最初のコンパイルオーバヘッドの後でも速くなければなりません。

2

バイトコードインタープリタでは、通常、命令フォーマットは、シフト演算子とマスク演算子を使用する非常に高速な「解析」用に設計されています。インタプリタは、命令を「解読する」ことを好む「解析」した後、直ちに仮想マシンの状態を更新し、次の命令の解読を開始する。したがって、バイトコードがインタプリタで処理された後、残りの部分は残っていません。

JITコンパイラでは、バイトは単一の命令よりも大きな単位で処理されます。最小単位は基本ブロックですが、現代のJITはより大きなパスを機械コードに変換します。これは変換ステップであり、変換ステップの出力はマシンコードです。元のバイトコードはメモリに残るかもしれませんが、実装には使用されません—したがって、実際の違いはありません。 (ただし、JITted仮想マシンのマシンコードは、ネイティブコードコンパイラによって生成されたマシンコードとは異なることがまだありますが)。

関連する問題