実行時にILまたはバイトコードを実行可能命令に変換するJITインタープリターを設計するとします。コードで変数名に遭遇するたびに、JITインタープリターはそれをそれぞれのメモリー・アドレスに変換する必要がありますよね?
JITインタープリターは、十分な方法で変数参照を解決するためにどのような技法を使用しますか?それらはハッシュを使用していますか、変数は事前にアドレスにコンパイルされていますか、それとも完全に何かが不足していますか?
Wikipedia からこの例を見てください:
for (int i = 2; i < 1000; i++) {
for (int j = 2; j < i; j++) {
if (i % j == 0)
continue outer;
}
System.out.println (i);
}
これはおおよそ次のバイトコードに変換されます:
0: iconst_2
1: istore_1
2: iload_1
3: sipush 1000
6: if_icmpge 44
9: iconst_2
10: istore_2
11: iload_2
12: iload_1
13: if_icmpge 31
16: iload_1
17: iload_2
18: irem
19: ifne 25
22: goto 38
25: iinc 2, 1
28: goto 11
31: getstatic #84; // Field Java/lang/System.out:Ljava/io/PrintStream;
34: iload_1
35: invokevirtual #85; // Method Java/io/PrintStream.println:(I)V
38: iinc 1, 1
41: goto 2
44: return
これは、変数がローカルアドレスに格納され、アドレスによって直接参照されるアセンブリ言語とよく似ています。元の変数名の痕跡はありません。
Javaバイトコードが非常に詳細にどのように機能するかについては、Oracleのドキュメントを参照してください。
さらに読む
Java®仮想マシン仕様。
変数は主に解析時に認識され、それらのバインディングとスコープは解析に関連しています。 JITコンパイル ライブラリは実際には変数を処理しません(そして、名前、タイプ、そしておそらくスコープについてはあまり気にしません)。
重要な点は、JITは「変数」ではなく「場所」または「値」を扱うということです。そのため、バイトコードは「変数」を認識しません(おそらく、関連するメタデータのデバッグを除く)。
JITを設計している(プログラミング言語を設計および実装していない)場合は、変数ではなく、場所と値の観点から考える必要があります。おそらく、正式な semantics の観点から考える必要があります(抽象VMの例 [〜#〜] secd [〜#〜] を見てください)。
SchemeまたはLISPを知っている場合は、Quennecの LISP In SmallPïeces の本を読むことをお勧めします。バイトコードを含む、LISPのような言語を実装する多くの方法を扱っています。