Javaの前置・後置インクリメントの内部実装を読みたい・その2

先日書いたJavaの前置インクリメントと後置インクリメントの件について、id:Nagiseさんからヒントを頂きました。

Javaではどうなるかという問題が未解決だったのでうれしいです。

が、JDKのコードを掘っているうちに寝落ちしてしまいました。

あまり成果はないですが、考えたことを忘れそうなので、分かったところまでメモしておきます。

Javaコンパイル動作メモ

Javaコンパイルすると、Javaコード→中間コード→マシンコードという変換が行われます。これをもう少し詳細に見てみます。

一般的に、コンパイラは次の動作を行います。

  1. プログラミング言語で書かれたコード
  2. 行読込み
  3. 字句解析
  4. 構文解析
  5. 中間コード作成
  6. 最適化(ここで最終的な中間語が得られる)
  7. コード作成
  8. 機械語コード

上のリストは、『コンパイラの構成と最適化』で説明されているコンパイラの論理的構造をもとに記述しています。下へいくほどマシンに近くなります。

字句解析、構文解析を経て、中間コードが得られます。中間コードの形式はランタイム次第で、抽象構文木、有効非循環グラフ、また別のもの(たとえば、上の本では3アドレスコードやRTLが紹介されています)など、様々です。

ここで、Javaでは木であるという話になるのでしょうが、自分はJava仮想マシン仕様を読んだことがないのでよくわかりませんどう見てもモグリです。本当にありがとうございました。今日から読みます。

上のリストの4番で作成された木を確認して、7番でどのような命令語にマッピングされかを把握できれば、幸福実現するということですね。

(追記)Javaの中間コードは、木構造ではないそうです。id:m11m さんからコメントで教えていただきました。(が、自分は実装レベルでまだ確認できていません。一応追記まで)

チラ見した箇所のメモ

  • jdk-6u23-jrl/hotspot/src/share/vm/opto/pars2.cpp

# 以下の文章は不正確かもしれないので、信じないでください。

上記のoptディレクトリ以下に格納されているのは、オペランドスタックの操作を実現するコードです。自分が間違って読んだのは、構文木の形をした中間語からマシン語を得る部分(たぶん)でした。

たとえば・・・

forやwhileなどの繰り返し構文では、ブロックの最後までいったら最初に戻る必要があります。つまり、ジャンプが繰り返し発生します。ジャンプを実現するために、アドレスのテーブルを生成します。

pars2.cppには、Parse::do_tableswitch関数と、Parse::do_lookupswitch関数があります。これら2つの関数は、ディシジョンツリーを形成し、最後にjump_switch_ranges関数を呼び出しています。jump_switch_ranges関数というのは再帰構造を持ち、ディシジョンツリーを切り替える動作をします。

・・・というようなコードが書かれています。木と関係ないですね。

javapで出力される命令について

先日の日記でjavapでiincやiloadを出していましたが、あれは命令語そのものではないようです。

バイトコードは、JVMを前提にした一種の機械語です。javapでは、アセンブラー風に出力していますが、実際は命令を表わす1バイトのオプコードに0バイトから数バイトのオペランドで構成されています。

http://monadc.com/proglanglist/jvm/22-bytecode.html

一次情報を探そうと思います。マシンの命令セットとの対応関係を把握したいです。

ひとまず、ここまで。