現在、独自の Java 仮想マシン実装の JIT コンパイル部分に取り組んでいます。私たちのアイデアは、指定された Java バイトコードをオペコードに単純に変換し、それらを実行可能メモリに書き込み、メソッドの先頭に直接呼び出すことでした。
指定された Java コードが次のようになると仮定します。
int a = 13372338;
int b = 32 * a;
return b;
ここで、次のアプローチが作成されました (指定されたメモリが 0x1000 で始まり、戻り値が eax であると想定しています)。
0x1000: first local variable - accessible via [eip - 8]
0x1004: second local variable - accessible via [eip - 4]
0x1008: start of the code - accessible via [eip]
Java bytecode | Assembler code (NASM syntax)
--------------|------------------------------------------------------------------
| // start
| mov edx, eip
| push ebx
|
| // method content
ldc | mov eax, 13372338
| push eax
istore_0 | pop eax
| mov [edx - 8], eax
bipush | push 32
iload_0 | mov eax, [edx - 8]
| push eax
imul | pop ebx
| pop eax
| mul ebx
| push eax
istore_1 | pop eax
| mov [edx - 4], eax
iload_1 | mov eax, [edx - 4]
| push eax
ireturn | pop eax
|
| // end
| pop ebx
| ret
これは、仮想マシン自体が行うのと同じようにスタックを使用するだけです。このソリューションに関する質問は次のとおりです。
- このコンパイル方法は実行可能ですか?
- この方法ですべての Java 命令を実装することさえ可能ですか? throw/instanceof や同様のコマンドはどのように変換できますか?