HotspotVMのstack map生成について

3
nari3 @nari3

JVMのJITコンパイラ周りがだいぶん魔窟で死にそう

2012-04-25 20:29:46
nari3 @nari3

HotspotVMのC1でコンパイルされたフレームのGC mapはコンパイル時に一緒に作成されるっぽいなぁ。動かしながら記録するんだと思ったが。コンパイル時に決定するのか。

2012-04-25 23:04:02
中村 実 @nminoru_jp

@nari3 GC mapというかstack mapを動かしながら記録するとは?

2012-04-25 23:08:33
Kris Mok @rednaxelafx

@nari3 そうですね。C2でもそうですよ。昔書いたノートが参考になれるかどうかわかりませんが http://t.co/SNECi4QZ ま、中国語の辺りは無視してもいいです。英語の部分だけ読めばいいと思います

2012-04-25 23:28:57
nari3 @nari3

@nminoru_jp コンパイル後のコードにstack mapを適宜記録するコードが入ってるのかな、と思ったんです。oopをどこかに書き込んだ時にそれをいちいち記録するようなものが…(コスト高すぎですね)。

2012-04-25 23:39:17
nari3 @nari3

@rednaxelafx おぉ、ありがとうございます!!参考にします!

2012-04-25 23:40:18
中村 実 @nminoru_jp

@nari3 JavaはBCIが決まるとスタックの高さと各スロットの型が一意に決まらなくてはならないという仕様があります(Gosling property)。分岐やループの合流があっても。違反したらクラスロード時にverifierに撥ねられます。だからいつでも合成可能なのです。

2012-04-25 23:45:34
nari3 @nari3

@nminoru_jp 合成というのはJITでコンパイルしたコードとふつうのバイトコードとの合成ですか? Gosling property…知りませんでした( ..)φメモメモ

2012-04-25 23:56:39
nari3 @nari3

もろもろ漁ってたら”Finding References in Java Stacks”というもろな論文が出てきた。2年前くらいに一度目を通して理解できなかったやつだ…

2012-04-25 23:58:00
中村 実 @nminoru_jp

@nari3 あ、なんか変なことを言ってますね。Java(インタプリータの)スタックフレームのstack mapはいつでも合成可能と言いたかったのです。でもcompiled codeのスタックフレームのstack mapもコンパイル時に決定しますから、実行時に記録は不要です。

2012-04-26 00:05:51
ひろかず @no5016

@nminoru_jp @nari3 JDK6以降だとクラスファイルにも入りましたよね。StackMapTableとかいう属性。ベリファイア向けで、GC向けでは無いですが。

2012-04-26 00:12:01
中村 実 @nminoru_jp

@no5016 @nari3 StackMapの解析ってノーヒントだとメソッドのバイトコード長Nに対してO(N^2)の計算量がかかって遅いですから。

2012-04-26 00:16:31
中村 実 @nminoru_jp

@no5016 @nari3 1.3だったか1.4だったか忘れましたがHotspot VMの過去のバージョンはGC時にstackmapを毎回生成して捨てる仕組みだったので、3~6万バイトぐらいあるメソッドの途中でGCが頻発するプログラムでGCの度に数秒止まっていました。

2012-04-26 00:19:50
ひろかず @no5016

@nminoru_jp @nari3 インタプリタだとGC時にオブジェクトマップ計算してるので、運の悪いところでGC停止食らうと、マイナーGCなのにエライ時間がかかるなんてことがあったような無かったような。

2012-04-26 00:20:20
nari3 @nari3

@nminoru_jp なるほどなるほど…。すみません、あと一点だけ…。stack mapの合成って具体的にはどういったことなんでしょうか?

2012-04-26 00:20:25
ひろかず @no5016

@nminoru_jp @nari3 つぶやきが丸被りでした( ;∀;)。JSPがそういう素敵なメソッド吐いてくれるんですよね。

2012-04-26 00:22:17
nari3 @nari3

@no5016 @nminoru_jp おぉッ、StackMapTable知りませんでした。調べておきます。

2012-04-26 00:26:01
中村 実 @nminoru_jp

@nari3 メソッドの先頭からバイトコード命令を読み込んでスタックの動作を抽象実行します。push時には型情報を積み、pop時には期待した型と一致しているかを確認します。分岐によって合流する場合はstack mapを比較して一致を確認します。

2012-04-26 00:28:27
中村 実 @nminoru_jp

@nari3 抽象実行は型が重要なので値は無視します。invoke系命令はスタックに上げ下げする幅と型だけ分かればいいので、呼び出し先を追いかけません。JSR命令の扱いが少し難しいです、これだけです。

2012-04-26 00:33:48
Kris Mok @rednaxelafx

@nari3 その実装はここです http://t.co/DZhZDaLi frame::oops_interpreted_do() -> OopMapCache::compute_one_oop_map() -> GenerateOopMap::compute_map()

2012-04-26 00:34:07
nari3 @nari3

@nminoru_jp なるほど!ありがとうございます!

2012-04-26 00:36:02
nari3 @nari3

@rednaxelafx ありがとうございます :D

2012-04-26 00:36:56
nari3 @nari3

http://t.co/CgDZ7Dlf この辺、もうちょっと書きなおさないと…。合流部分は書けてなかった。

2012-04-26 00:37:56