HotspotVMのC1でコンパイルされたフレームのGC mapはコンパイル時に一緒に作成されるっぽいなぁ。動かしながら記録するんだと思ったが。コンパイル時に決定するのか。
2012-04-25 23:04:02@nari3 そうですね。C2でもそうですよ。昔書いたノートが参考になれるかどうかわかりませんが http://t.co/SNECi4QZ ま、中国語の辺りは無視してもいいです。英語の部分だけ読めばいいと思います
2012-04-25 23:28:57@nminoru_jp コンパイル後のコードにstack mapを適宜記録するコードが入ってるのかな、と思ったんです。oopをどこかに書き込んだ時にそれをいちいち記録するようなものが…(コスト高すぎですね)。
2012-04-25 23:39:17@nari3 JavaはBCIが決まるとスタックの高さと各スロットの型が一意に決まらなくてはならないという仕様があります(Gosling property)。分岐やループの合流があっても。違反したらクラスロード時にverifierに撥ねられます。だからいつでも合成可能なのです。
2012-04-25 23:45:34@nminoru_jp 合成というのはJITでコンパイルしたコードとふつうのバイトコードとの合成ですか? Gosling property…知りませんでした( ..)φメモメモ
2012-04-25 23:56:39もろもろ漁ってたら”Finding References in Java Stacks”というもろな論文が出てきた。2年前くらいに一度目を通して理解できなかったやつだ…
2012-04-25 23:58:00@nari3 あ、なんか変なことを言ってますね。Java(インタプリータの)スタックフレームのstack mapはいつでも合成可能と言いたかったのです。でもcompiled codeのスタックフレームのstack mapもコンパイル時に決定しますから、実行時に記録は不要です。
2012-04-26 00:05:51@nminoru_jp @nari3 JDK6以降だとクラスファイルにも入りましたよね。StackMapTableとかいう属性。ベリファイア向けで、GC向けでは無いですが。
2012-04-26 00:12:01@no5016 @nari3 StackMapの解析ってノーヒントだとメソッドのバイトコード長Nに対してO(N^2)の計算量がかかって遅いですから。
2012-04-26 00:16:31@no5016 @nari3 1.3だったか1.4だったか忘れましたがHotspot VMの過去のバージョンはGC時にstackmapを毎回生成して捨てる仕組みだったので、3~6万バイトぐらいあるメソッドの途中でGCが頻発するプログラムでGCの度に数秒止まっていました。
2012-04-26 00:19:50@nminoru_jp @nari3 インタプリタだとGC時にオブジェクトマップ計算してるので、運の悪いところでGC停止食らうと、マイナーGCなのにエライ時間がかかるなんてことがあったような無かったような。
2012-04-26 00:20:20@nminoru_jp なるほどなるほど…。すみません、あと一点だけ…。stack mapの合成って具体的にはどういったことなんでしょうか?
2012-04-26 00:20:25@nari3 メソッドの先頭からバイトコード命令を読み込んでスタックの動作を抽象実行します。push時には型情報を積み、pop時には期待した型と一致しているかを確認します。分岐によって合流する場合はstack mapを比較して一致を確認します。
2012-04-26 00:28:27@nari3 抽象実行は型が重要なので値は無視します。invoke系命令はスタックに上げ下げする幅と型だけ分かればいいので、呼び出し先を追いかけません。JSR命令の扱いが少し難しいです、これだけです。
2012-04-26 00:33:48@nari3 その実装はここです http://t.co/DZhZDaLi frame::oops_interpreted_do() -> OopMapCache::compute_one_oop_map() -> GenerateOopMap::compute_map()
2012-04-26 00:34:07