Successfully reported this slideshow.
Your SlideShare is downloading. ×

20221226_TITECH_lecture_ishizaki_public.pdf

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 75 Ad

More Related Content

Slideshows for you (20)

Similar to 20221226_TITECH_lecture_ishizaki_public.pdf (20)

Advertisement

More from Kazuaki Ishizaki (20)

Recently uploaded (20)

Advertisement

20221226_TITECH_lecture_ishizaki_public.pdf

  1. 1. 2022年12月26日 日本アイ・ビー・エム(株) 東京基礎研究所 石崎 一明 数理・計算科学特論B プログラミング言語処理系の最先端実装技術 第6講 inliningとdevirtualization 1
  2. 2. 自己紹介 ▪ プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 2 石崎 一明(いしざき かずあき) http://ibm.biz/ishizaki 1992年3月 早稲田大学理工学研究科修士課程電気工学専攻を修了。 1992年4月 日本アイ・ビー・エム(株)入社、東京基礎研究所勤務。以来、並列化コンパイラ、動的コン パイラ、アプリケーション最適化、などの研究に従事。最近は、AIプロセッサのソフトウェ アスタックの研究開発に従事。現在、同研究所シニア・テクニカル・スタッフ・メンバー 2002年12月 早稲田大学理工学研究科にて、博士(情報科学)を取得。 2008年から2009年まで、IBMワトソン研究所に滞在。 2004年に情報処理学会業績賞受賞。ACM Distinguished Member、情報処理学会シニアメンバー 主な学会活動 2004~2005年 日本ソフトウェア科学会PPL 2004/2005ワークショップ プログラム委員 2006年 日本ソフトウェア科学会PPL 2006ワークショップ プログラム共同委員長 2008年 PC member of ACM OOPSLA 2008 Conference 2007~2009年度 日本ソフトウェア科学会プログラミング論研究会 運営委員 2011~2014年度 情報処理学会アーキテクチャ研究会 運営委員 2015~2019年 日本ソフトウェア科学会理事 2016~2017年度 情報処理学会プログラミング研究会 運営委員 2018~2021年度 情報処理学会プログラミング研究会 幹事 2017~2022年 PC member of IEEE BigData 2017 主なオープンソース活動: Apache SparkとApache Arrowのコミッター
  3. 3. 今日の講義の内容 ▪ メソッド呼び出しの実行時間に関する最適化 – Method inlining ▪ 直接メソッド呼び出しにおいてInliningするメソッドの決定 – メソッド呼び出しのdevirtualization ▪ 仮想メソッド呼び出しから直接メソッド呼び出しへの変換 ▪ 異なるコード間の実行の遷移について – コンパイルコードからインタープリタへ – インタープリタからコンパイルコードへ プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 3 今日の話の前提は、コンパイル単位 はメソッドです。 メソッド以外のコンパイル単位の話 は、1/16の9講で。
  4. 4. 今日の授業でわかる(はずの)こと(1/2) ▪ メソッド呼び出しの最適化 – Super.div()の呼び出しとその実行を、どうやって高速化するか? – s.add()のような、仮想メソッド呼び出し(呼び出し先が一意に決まらない可能 性がある)の実行を、どうやって高速化するか? プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 4 class Super { public int add(int i) { return i + 9; } public int mul(int i) { return i * 9; } public static final int div(int i) { return (i != 0) ? (4 / i) : 0;} public static int calc() { int r = Super.div(2) + 3; return r; } } class Sub1 extends Super { public int add(int i) { return i + 1; } public int foo(...) { ... } public static int calc1(Super s) { int r = s.add(2) + 3; return r; } }
  5. 5. 今日の授業でわかる(はずの)こと(2/2) ▪ メソッドの実行遷移の最適化 – s.add()でSub2.add()がよく呼ばれることがわかった時、”長いコード”をコンパ イルしないようにできないか? – 1度だけ呼び出されるmain()メソッド内にあるSuper.div()へのメソッド呼び出 しを、実行時コンパイルでどうやってmethod inliningするか? プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 5 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int r = s.add(-2); if (r != 0) { ... // 長いコード } return r; } } class Super { public static final int div(int i) { return (i != 0) ? (4 / i) : 0;} public static void main(String args[]) { for (int i = 0; i < 100000; i++) { int r = Super.div(2) + 3; System.println(r); } } }
  6. 6. Method inlining プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 6
  7. 7. Method inlining(inline expansion – インライン展開) ▪ Advanced compiler design implementation 15.2より – Procedure integration, also called automatic inlining, replaces calls to procedures with copies of their bodies. It can be a very useful optimization, because it changes calls from opaque objects that may have known effects on aliased variable and parameters to local code that not only exposes its effect but that can be optimized of the calling procedure. プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 7
  8. 8. Method inlining(inline expansion – インライン展開) ▪ Advanced compiler design implementation 15.2より – Procedure integration, also called automatic inlining, replaces calls to procedures with copies of their bodies. It can be a very useful optimization, because it changes calls from opaque objects that may have known effects on aliased variable and parameters to local code that not only exposes its effect but that can be optimized of the calling procedure. プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 8 あるメソッド呼び出しによって呼びされるメソッド (呼び出し先)の本体のコピーで、メソッド呼び出 しを置き換える ・わからないオブジェクトを明確にする ・パラメータをローカルなコードにする ・呼び出し手続きを最適化するのに有用
  9. 9. Method inlining(inline expansion – インライン展開) ▪ 実際の適用例 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 9 class Super { public static final int div(int i) { return (i != 0) ? (4/i) : 0; } public static int calc() { int r = Super.div(2); return r; } } public static int calc() { int r = (2 != 0) ? (4 / 2) : 0; return r; } プログラム
  10. 10. なぜmethod inliningを行うのか? ▪ コンパイラによって生成されるコードの質の問題の軽減 – メソッド呼び出しのオーバヘッドの削減 – コンパイル単位を大きくして、最適化をより適用したい ▪ オブジェクト指向言語では、一般にメソッドの大きさが小さくなりがち ▪ 仮想メソッドの場合にはdevirtualizationが必要 ▪ プロセッサ上での問題の軽減 – メソッド呼び出しが使用する命令が、プロセッサ内のパイプライン実行を乱す ▪ 直接メソッド呼び出し ▪ 仮想メソッド呼び出し プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 10
  11. 11. method inliningの前提 ▪ 元の動作を変更してはいけない – 外部から見える値(volatile変数など) – 例外・同期が起きた時 – メソッド呼び出しのスタックトレース ▪ 実行時間をMethod inliningしないときより減らしたい – ハードウェアのリソース(メモリ、命令キャッシュなど)を使いすぎない ▪ コンパイル時間の増加をほどほどに プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 11
  12. 12. 直接メソッド呼び出し(direct method call) ▪ コンパイル時に、プログラム上の情報から呼び出し先が一意に決定可能 – 直接分岐命令(call address)の使用 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 12 class Super { public static final int div(int i) { ... } public static int calc() { ... Super.div(2) ... ... } } ... call method_div ... method_div: ... ret プログラム 機械語命令
  13. 13. 仮想メソッド呼び出し(virtual method call) ▪ コンパイル時に、呼び出し先が一意に決定できない – 実行時に呼び出し先を決定する機構(表引き、など)が必要 – 間接分岐命令(call reg)の使用 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 13 class Sub1 extends Super { public int add(int i) { ... } public int sub(int i) { ... } public static int calc1(Super s) { ... s.add(2) ... ... } } ... // r3 = object of Super ld r2, (r3+offset_class_in_object) ld r1, (r2+offset_vtableadd_in_class) ld r0, (r1+offset_code_in_method) call r0 ... プログラム 機械語命令 r3 Super s
  14. 14. 仮想メソッド呼び出し(virtual method call) ▪ クラステーブルへのメモリ参照 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 14 class Sub1 extends Super { public int add(int i) { ... } public int sub(int i) { ... } public static int calc1(Super s) { ... s.add(2) ... ... } } ... // r3 = object of Super ld r2, (r3+offset_class_in_object) ld r1, (r2+offset_vtable_add_in_class) ld r0, (r1+offset_code_in_method) call r0 ... プログラム 機械語命令 mul foo virtual table add r3 r2 sub 同じメソッドはクラス階層内で 同じオフセットを持つ Super s class Sub1
  15. 15. 仮想メソッド呼び出し(virtual method call) ▪ メソッドテーブルへのメモリ参照 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 15 class Sub1 extends Super { public int add(int i) { ... } public int sub(int i) { ... } public static int calc1(Super s) { ... s.add(2) ... ... } } ... // r3 = object of Super ld r2, (r3+offset_class_in_object) ld r1, (r2+offset_vtable_add_in_class) ld r0, (r1+offset_code_in_method) call r0 ... プログラム 機械語命令 mul foo add r3 r2 r1 sub Super s class Sub1 method Sub1.add virtual table 同じメソッドはクラス階層内で 同じオフセットを持つ code
  16. 16. 仮想メソッド呼び出し(virtual method call) ▪ 呼び出し先アドレス取得のメモリ参照 ▪ 間接分岐命令(call reg)の使用 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 16 class Sub1 extends Super { public int add(int i) { ... } public int sub(int i) { ... } public static int calc1(Super s) { ... s.add(2) ... ... } } ... // r3 = object of Super ld r2, (r3+offset_class_in_object) ld r1, (r2+offset_vtable_add_in_class) ld r0, (r1+offset_code_in_method) call r0 ... プログラム 機械語命令 mul foo add code r3 r2 r1 binary code r0 sub Super s class Sub1 method Sub1.add virtual table 同じメソッドはクラス階層内で 同じオフセットを持つ
  17. 17. (昔の)プロセッサ上での直接分岐の問題 ▪ 直接分岐のオーバヘッド – 命令アドレスが連続する次の命令アドレス、ではなくなるので、命令パイプ ライン内の実行を乱す(ハザードの発生) プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 17 call method_div add r3 = r11, r12 mov r4 = r3 method_div: div r5 = r3, r4 IFetch IDec Exec WB
  18. 18. (昔の)プロセッサ上での直接分岐の問題 ▪ call命令のフェッチ プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 18 IFetch call method_div add r3 = r11, r12 mov r4 = r3 method_div: div r5 = r3, r4
  19. 19. (昔の)プロセッサ上での直接分岐の問題 ▪ call命令のデコード プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 19 IFetch IDec IFetch call method_div add r3 = r11, r12 mov r4 = r3 method_div: div r5 = r3, r4
  20. 20. (昔の)プロセッサ上での直接分岐の問題 ▪ call命令の実行による、次に実行する命令のアドレス(method_div)の決 定 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 20 IFetch IDec Exec IFetch IDec IFetch call method_div add r3 = r11, r12 mov r4 = r3 method_div: div r5 = r3, r4 method_div
  21. 21. (昔の)プロセッサ上での間接分岐の問題 ▪ 飛び先のdiv命令のフェッチ とともに、フェッチ・デコードしていた命令の破棄 – 最近のプロセッサは、命令パイプラインの早い段階(IDecなど)で分岐先アド レスを生成するので、ハザードは少ない プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 21 IFetch IDec Exec WB IFetch IDec Exec WB IFetch IDec Exec WB IFetch IDec Exec WB call method_div add r3 = r11, r12 mov r4 = r3 method_div: div r5 = r3, r4 method_div
  22. 22. (昔の)プロセッサ上での間接分岐の問題 ▪ 間接分岐のオーバヘッド – 分岐先の命令アドレスが決定するのに時間がかかるので、命令パイプライン 内の実行を乱し、ハザードを発生する プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 22 load r0,...(r1) call r0 ... method_Sub1add: ... IFetch IDec Exec WB
  23. 23. (昔の)プロセッサ上での間接分岐の問題 ▪ load命令のフェッチ プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 23 IFetch load r0,...(r1) call r0 ... method_Sub1add: ...
  24. 24. (昔の)プロセッサ上での間接分岐の問題 ▪ load命令のデコード プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 24 IFetch load r0,...(r1) call r0 ... method_Sub1add: ... IDec IFetch
  25. 25. (昔の)プロセッサ上での間接分岐の問題 ▪ load命令の実行による、r0の内容の確定 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 25 IFetch load r0,...(r1) call r0 ... method_Sub1add: ... IDec IFetch Exec IDec IFetch r0
  26. 26. (昔の)プロセッサ上での間接分岐の問題 ▪ call命令の実行による、次に実行する命令のアドレス (method_Sub1add)の決定 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 26 IFetch load r0,...(r1) call r0 ... method_Sub1add: ... IDec IFetch Exec IDec IFetch WB Exec IDec method_Sub1add
  27. 27. (昔の)プロセッサ上での間接分岐の問題 ▪ 飛び先の命令のフェッチ とともに、フェッチ・デコードしていた命令の破棄 – 最近のプロセッサは命令パイプラインの早い段階で(IDecなど)、強力な分岐 予測機構によって、分岐先アドレスを生成するので、ハザードは少ない ▪ 命令アドレスから、過去の分岐履歴に基づいて分岐先アドレスを予測する プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 27 IFetch load r0,...(r1) call r0 ... method_Sub1add: ... IDec IFetch Exec IDec IFetch r0 WB Exec IDec IFetch IDec Exec WB Exec WB WB method_Sub1add
  28. 28. ABIのコードの問題 ▪ 現実の処理系におけるメソッド呼び出しの際には、ソースコードからは見 えない、application binary interface(ABI)にもとづいた処理が必要になる プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 28 // s.add(2)の呼び出し ... call method_add ... 機械語命令
  29. 29. ABIのコードの問題 ▪ 現実の処理系におけるメソッド呼び出しの際には、ソースコードからは見 えない、application binary interface(ABI)にもとづいた処理が必要になる – メソッド呼び出しがなくなれば、引数設定やスタックフレーム作成は不要 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 29 // s.add(2)の呼び出し ... mov r4 = 2 // 第2引数 2 mov r3 = r10 // 第1引数 s call method_add mov r4 = r3 // 戻り値 ... 機械語命令 // s.add(2)のメソッド入り口 method_add: st (sp+8), return // 前のスタックフレーム上に // 戻りアドレスを保存 mov r0, sp // 古いスタック値の保存 sub sp = sp - 64 // 新しいスタックの作成 st (sp+0), r0 // 新しいスタックから // 古いスタックへのリンク作成 mov r16 = r4 // 第2引数の受け取り ... return sp sp Return lower address スタックフレーム s.add() sp+8
  30. 30. 複雑な引数を渡す際のコードの問題 ▪ 引数渡しの際に、プログラムからは見えない、重い処理を伴うことがある – 可変長引数 – キーワード引数(ruby, pythonなど) プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 30 class Super { void print(int i, int j, int k) { System.out.printf(“%d %d¥n”, i, j); } } プログラム def add(a:1, b:2) a + b end add(a: 1.2, b: 3.4) プログラム
  31. 31. 複雑な引数を渡す際のコードの問題 ▪ 引数渡しの際に、プログラムからは見えない、重い処理を伴うことがある – 可変長引数 ▪ Javaの場合、オブジェクトが生成される – キーワード引数(ruby, pythonなど) ▪ ハッシュ表を生成して渡している プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 31 class Super { void print(int i, int j, int k) { System.out.printf(“%d %d¥n”, i, j); } } プログラム def add(a:1, b:2) a + b end add(a: 1.2, b: 3.4) class Super { void print(int i, int j, int k) { System.out.printf("%d %d¥n", new Object[] { Integer.valueOf(i), Integer.valueOf(j) }); } } def add(a:1, b:2) a + b end add(a: 1.2, b: 3.4) プログラム {a=>1.2, b=>3.4}
  32. 32. 生成されるコードの問題の軽減 ▪ コンパイル単位の範囲の増加 – 最適化(特にデータフロー解析)の適用範囲が広がる プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 32 class Super { public static final int div(int i) { return (i != 0) ? (4 / i) : 0;} public static int calc() { int r = Super.div(2) + 3; return r; } } Super.div(2)を、呼び出し先のコードで置き換え public static int calc() { int r = ((2 != 0) ? (4 / 2) : 0) + 3; return r; } コンパイル時に式を評価 public static int calc() { return 5; }
  33. 33. Method inliningを行うメソッドの特定 ▪ 呼び出し先メソッドが、容易に一意に特定できる場合 – 直接メソッド呼び出し ▪ 呼び出し先メソッドの特定が、容易では無い場合 – 仮想メソッド呼び出し ▪ この後お話します(devirtualization) プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 33 class Super { public int add(int i) { return i + 9; } public static final int div(int i) { return (i != 0) ? (4 / i) : 0;} public static int calc() { int r = Super.div(2) + 3; return r; } }
  34. 34. Method inliningを行うか行わないかの判断(1/2) ▪ (私見では)決定解はこれまでにない。 時代(プロセッサアーキテクチャ、言語)によって良い解法が異なるので は? – 静的情報 ▪ 呼び出し先メソッドの大きさ • コンパイル時間が長くならないに • 命令キャッシュが溢れないように ▪ 制御フローの形 • 呼び出し先メソッドを先読みして、method inliningを行った場合最適化が適用できるか判断 する ▪ … – 動的情報 ▪ 実行中に集められた実行時のメソッド実行頻度に基づく ▪ ハードウェアカウンタから、メソッド実行頻度を推定可能 ▪ 実行中に集められた引数の値にもとづいて、 method inliningを行った場合最適化が 適用できるか判断する ▪ … プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 34
  35. 35. Method inliningを行うか行わないかの判断(2/2) ▪ 機械学習、深層学習の利用 – Automatic Construction of Inlining Heuristics using Machine Learning ▪ Inliningするしないの判断を、 機械学習や、教師なし学習の結果に基づいて行う – LLVMのMLGO (Machine Learning Guided Compiler Optimizations Framework) ▪ Inliningするしないの判断を、強化学習の学習結果に基づいて行う プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 35
  36. 36. Devirtualization プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 36
  37. 37. Method inliningを行う呼び出し先メソッドの特定 ▪ メソッドの呼び出し先を一意に特定することが難しい場合 – 仮想メソッド呼び出し – インターフェースメソッド呼び出し プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 37 Sub1.add() Super.add() Sub2.add() ... call s.add()
  38. 38. Devirtualizationによって特定 ▪ 複数の呼び出し先を、特定した1つとその他、に分ける – 仮想呼び出しではなくなっている、 のでdevirtualization(脱仮想化) ▪ 分ける方法 – Guarded devirtualization – Direct devirtualization プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 38 Sub1.add() Super.add() Sub2.add() ... call Sub2.add() call s.add() call s.add()
  39. 39. Guarded devirtualizationによって特定 ▪ 複数の呼び出し先を条件分岐(ガード)によって、特定した1つとその他、 に分ける ▪ 実行時情報などからガードを挿入して、呼び出し先を特定 – Method test [Calder1994] – Class test [Grove1995] ▪ 複数の呼び出し先を特定 – Polymorphic inline cache [Chambers1991] プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 39 Sub1.add() Super.add() Sub2.add() ... call s.add() ガード call Sub2.add() call s.add()
  40. 40. Direct devirtualizationによって特定 ▪ プログラム解析などによってガード無しで1つであることを特定する – 解析の結果、複数個に特定できる場合もある ▪ ガード無しで、1つの呼び出し先を特定 – Type analysis [Chamber1990] – Class hierarchy analysis [Dean1995, Ishizaki2000] – Rapid type analysis [Bacon1996] プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 40 Super.mul() ... call s.mul() call Super.mul()
  41. 41. Guarded devirtualizationの手法 ▪ 元のコード ▪ 直接メソッド呼び出しもしくはmethod inliningされているコードを呼び 出してよいか、ガードの比較結果に基づいて判断する。 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 41 ... // r3 = object of Super ld r2, (r3+offset_class_in_object) ld r1, (r2+offset_vtable_add_in_class) ld r0, (r1+offset_code_in_method) call r0 ... Class test(クラスの一致で判断) mul foo add code r2 r1 binary code r0 sub Super s class Sub1 method Sub1.add virtual table // r3 = object in s ld r2, offset_class_in_object(r3) if (r2 == #address_of_classSub2) { call Sub2.add または exec inlined code } else { ld r1, offset_vtable_add_in_class(r2) ld r0, offset_code_in_method(r1) call r0 } // r3 = object in s ld r2, offset_class_in_object(r3) ld r1, offset_vtable_add_in_class(r2) if (r1 == #address_of_methodSub2add) { call Sub2.add または exec inlined code } else { ld r0, offset_code_in_method(r1) call r0 } 機械語命令 Method test(メソッドの一致で判断) 機械語命令 r3
  42. 42. Class testとMethod testの違い ▪ Method testのほうがメモリからのロードが1つ多いが、呼び出し先を特定 する精度が高い – 下記のプログラムにおいて、sにSub3のインスタンスが渡されると ▪ Class test(s.mul()はSuperでガードされていると仮定)では、 Super != Sub3でガードの条件が成立せず、仮想メソッド呼び出しを実行する必要があ る。 ▪ Method testでは、&Super.mul() == &Sub3.mul()となりガードの条件が成立し、呼び出 し先を一意に決定することができ、直接メソッド呼び出しを実行可能。 • Sub3ではmul()が定義されていないが、Superからvirtual tableを継承して同じメソッド情報を指 す プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 42 class Sub3 class Super mul() public int foo(Super s) { ... s.mul(3) ... }
  43. 43. Polymorphic inline cache (PIC) ▪ 複数の呼び出し先を持つメソッド呼び出しの高速化のために、複数のガード を挿入する – 複数のメソッドがオーバライドしている仮想メソッド呼び出し – 複数のクラスがimplementしているインターフェース呼び出し プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 43 // r3 = object in s Ld r2, offset_class_in_object(r3) if (r2 == #address_of_classSuper) { call Super.add または exec inlined code else if (r2 == #address_of_classSub1) { call Sub1.add または exec inlined code else if (r2 == #address_of_classSub2) { call Sub2.add または exec inlined code } else { ld r1, offset_vtableadd_in_class(r2) ld r0, offset_code_in_method(r1) call r0 } 機械語命令 class Sub1 add() class Sub2 add() class Super add()
  44. 44. Direct devirtualizationの必要性 ▪ ガードを挿入したguarded devirtualization、はSmalltalkなどの動的型付け 言語で1980年代に盛んに研究されてきた – 仮想メソッド呼び出しの実行コストが大きいので、実行時間の短縮に貢献 ▪ Javaなどの静的型付け言語では、仮想メソッド呼び出しの実行コストと、 guarded devirtualization+直接呼び出しによる実行コストは、あまり差が ない – guarded devirtualization+method inlining – ガード無しのdirect devirtualizationによる、実行時間の短縮の要求 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 44 動的型付け言語でprototypeベースのような構造が動的に変わるような処理系 (例えばJavaScript)での問題と解法については、下記の論文などがあります “Improving JavaScript Performance by Deconstructing the Type System”, 2014
  45. 45. Direct devirtualizationの手法 ▪ クラス階層解析(Class hierarchy analysis, CHA)を必要としない方法 – Type analysis [Chamber1990] – Value type analysis (VTA) [Sundaresan2000] – Extended type analysis (XTA) [Tip2000] ▪ Type analysisをメソッド間に拡張 ▪ クラス階層解析を必要とする方法 – Class hierarchy analysis (CHA) [Dean1995] – Rapid type analysis (RTA) [Bacon1996] – Class hierarchy analysis with code patching [Ishizaki2000] プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 45
  46. 46. 形解析(type analysis) ▪ メソッド呼び出しのレシーバーに到達するオブジェクトの型を データフロー解析によって求める。 ▪ 型が一意に決定する場合には、呼び出し先のメソッドを一意に決定可能。 – 仮想メソッド呼び出しを、直接メソッド呼び出しに変換、もしくはMethod inliningが可能 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 46 public int bar() { Super s = new Sub1(); ... ... s.add(4) ... } ... // r3 = s call method_Sub1add ... method_Sub1add: ... ret プログラム 機械語命令 s.add()のsに到達するのは Sub1だけなので、 Sub1.add()が必ず呼び出される
  47. 47. クラス階層解析(Class hierarchy analysis - CHA) ▪ プログラム全体のクラス階層でどのメソッドが定義されているかを調べる – メソッド呼び出しのレシーバーの型になったとき、とり得るメソッドを集める ▪ 集合内のメソッド数が少ないほど、devirtualizationの効率が高くなる プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 47 class Sub3 class Super mul() Super: {Super.mul()} Sub3: {Super.mul()} レシーバーの型がClassと なった時とり得る メソッド集合 {} SuperかSub3クラスのどちら でも、呼び出される実装は Super.mul() Sub3クラスだけだが、 呼び出される実装は Super.mul() public int bar() { ... ... s.mul(4) ... }
  48. 48. クラス階層解析(Class hierarchy analysis - CHA) ▪ Javaの場合、実行中にクラスロード・アンロードが発生するので、クラス階 層を常にメンテナンスする必要がある。 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 48 class Sub3 class Super mul() Super: {Super.mul()} Sub3: {Super.mul()} class Sub3 class Sub4 mul() class Super mul() Super: {Super.mul(), Sub4.mul()} Sub3: {Super.mul()} レシーバーの型がClassと なった時とり得る メソッド集合 {} Sub4: {Sub4.mul()} Sub3がロードされる
  49. 49. Rapid type analysis (RTA) ▪ CHAより、とりえるメソッド集合を減らす方法 ▪ CHAに加えて、プログラム中でクラスがinstantiation(Javaならnew)され てるか調べる。 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 49 class Sub3 class Sub4 mul() class Super mul() class Sub5 mul() Super: {Super.mul(), Sub4.mul(), Sub5.mul()} Sub3: {Super.mul()} Sub4: {Sub4.mul(), Sub5.mul()} レシーバーの型がClassとなった時 とり得るメソッド集合 {} Sub5: {Sub5.mul()}
  50. 50. Rapid type analysis (RTA) ▪ CHAに加えて、プログラム中でクラスがinstantiation(Javaならnew)され てるか調べる。 – Instantiationされないクラスのメソッド(Sub4.mul())はメソッド集合に入れない プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 50 プログラム中に、 new Super(), new Sub3(), new Sub5()が存在し、 new Sub4()が 存在しないならば class Sub3 class Sub4 mul() class Super mul() class Sub5 mul() Super: {Super.mul(), Sub4.mul(), Sub5.mul()} Sub3: {Super.mul()} Sub4: {Sub4.mul(), Sub5.mul()} レシーバーの型がClassとなった時 とり得るメソッド集合 {} Sub5: {Sub5.mul()} Super: {Super.mul(), Sub4.mul(), Sub5.mul()} Sub3: {Super.mul()} Sub4: {Sub4.mul(), Sub5.mul()} レシーバーの型がClassとなった時 とり得るメソッド集合 {} Sub5: {Sub5.mul()} RTA適用
  51. 51. CHAやRTAを使ったdevirtualization ▪ CHAやRTAで求めたメソッド集合を用いて、メソッド呼び出しのレシーバー のオブジェクトの型から、呼び出し先となり得るメソッド集合を取得する ▪ メソッド集合の中にメソッドが1つだけ存在するならば、呼び出し先のメ ソッドを一意に決定可能。 – 直接メソッド呼び出しに変換、もしくはmethod inliningが可能 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 51 class Sub3 class Super mul() public int foo(Super s) { ... s.mul(3) ... } ... // r3 = s call method_Supermul ... method_Supermul: ... ret s.mul()では Super.mul()が 必ず呼び出される Super: {Super.mul()} Sub3: {Super.mul()} とり得る メソッド集合 {} 機械語命令
  52. 52. CHA(RTA)とcode patchingによるdevirtualization ▪ Javaではクラス階層が固定ではないので、ある時点のコンパイル時に一意 であった呼び出し先メソッドが、突然複数になることがある – コンパイル時にs.mul()の呼び出し先メソッドが一意であれば、直接メソッド呼 び出しと間接メソッド呼び出しの両方を用意し、直接メソッド呼び出しを実行 する。 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 52 class Sub3 class Super mul() public int foo(Super s) { ... s.mul(3) ... } ... call method_Supermul // 直接呼び出し after_call: ... dynamic_call: ld r2,(r3+offset_class_in_object) ld r1,(r2+offset_vtable_mul_in_class) ld r0,(r1+offset_code_in_method) call r0 // 間接呼び出し jmp after_call Super: {Super.mul()} とり得る メソッド集合 {} 機械語命令
  53. 53. CHA(RTA)とcode patchingによるdevirtualization ▪ Javaではクラス階層が固定ではないので、ある時点のコンパイル時に一意 であった呼び出し先メソッドが、突然複数になることがある – Sub4が動的クラスローディングされた結果、メソッドmul()がオーバライドされ た時は、コードを書き換えて間接メソッド呼び出しを実行する プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 53 class Sub3 class Super mul() public int foo(Super s) { ... s.mul(3) ... } ... jmp dynamic_call after_call: ... dynamic_call: ld r2,(r3+offset_class_in_object) ld r1,(r2+offset_vtable_mul_in_class) ld r0,(r1+offset_code_in_method) call r0 // 間接呼び出し jmp after_call Super: {Super.mul(), Sub4.mul()} 機械語命令 class Sub4 mul()
  54. 54. Devirtualization+method inliningによる問題点 ▪ Method inliningした場合と仮想メソッド呼び出しの制御が合流する – データーフロー解析結果(rの値は?)の精度が悪くなる ▪ Method test, Class test ▪ CHA + code patching ▪ 解決手段 – Splitting – Deoptimization [Holze1992] ▪ すこし後に説明します プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 54 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int r = s.add(-2); if (r != 0) { ... // 長いコード } return r; } } r = 0 ガード r = Sub2.add(-2) -> -2 + 2 = 0 call s.add(-2) r != 0 長いコード
  55. 55. Splitting ▪ コードを複製して、制御の合流点の位置を変更して、データフロー解析結 果の精度を下げない(条件分岐におけるrの値は?) – 場合によっては、複製するコード量が 増えることがある プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 55 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int r = s.add(-2); if (r != 0) { ... // 長いコード } return r; } } r = 0 ガード r = Sub2.add(-2) -> -2 + 2 = 0 call s.add(-2) r != 0 長いコード r != 0 r != 0
  56. 56. Splitting ▪ 左側のパスは、r = 0が確定しているので、条件分岐を除去可能 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 56 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int r = s.add(-2); if (r != 0) { ... // 長いコード } return r; } } r = 0 ガード r = Sub2.add(-2) -> -2 + 2 = 0 call s.add(-2) 長いコード r != 0 r != 0
  57. 57. 今日の授業でわかる(はずの)こと ▪ メソッド呼び出しの最適化 – Super.div()の呼び出しとその実行を、どうやって高速化するか?→ method inlining – s.add()のような、仮想メソッド呼び出し(呼び出し先が一意に決まらない可能 性がある)の実行を、どうやって高速化するか?→ devirtualization プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 57 class Super { public int add(int i) { return i + 9; } public int mul(int i) { return i * 9; } public static final int div(int i) { return (i != 0) ? (4 / i) : 0;} public static int calc() { int r = Super.div(2) + 3; return r; } } class Sub1 extends Super { public int add(int i) { return i + 1; } public int foo(...) { ... } public static int calc1(Super s) { int r = s.add(2) + 3; return r; } }
  58. 58. 今日の授業でわかる(はずの)こと ▪ メソッドの実行遷移の最適化 – s.add()でSub2.add()がよく呼ばれることがわかった時、”長いコード”をコンパ イルしないようにできないか?→ splittingでデータフロー解析の精度を改善す る、がまだコンパイルは必要 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 58 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int r = s.add(-2); if (r != 0) { ... // 長いコード } return r; } }
  59. 59. コードの実行遷移 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 59
  60. 60. コンパイルコードとインタープリタ間の実行の遷移について ▪ コンパイルコードからインタープリタへ ▪ インタープリタからコンパイルコードへ – 通常はメソッドの先頭で遷移する – メソッドの中間に遷移したいことがある ▪ メソッドの一部だけコンパイルしたい プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 60 インタープリタのコード foo() { ... bar(); ... } コンパイルされたコード bar() { ... ... } インタープリタのコード foo() { bar() { ... ... bar(); ... ... } } コンパイルされたコード bar() { ... ... }
  61. 61. 用語について ▪ 統一された用語の使い方がないように思われる – コンパイルコードからインタープリタへ – インタープリタからコンパイルコードへ プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 61 コンパイルコードから インタープリタへ インタープリタから コンパイルコードへ Self (コンパイルコードから別のコンパイルコードへ) Deoptimization ない OpenJDK Deoptimization On-stack replacement (OSR) IBM Java, OpenJ9 Deoptimization using OSR Dynamic loop transfer Jikes RVM (コンパイルコードから別のコンパイルコードへ) OSR OSR V8 (コンパイルコードから別のコンパイルコードへ) Deoptimization OSR LLVM JIT Optimize OSR Deoptimize OSR
  62. 62. ▪ コンパイラ内部表現は、ある条件を満たさな かったとき、分岐先がコンパイルコード外となる – コンパイルするコード量が減る – コンパイラコード内の制御合流点が減る ▪ 典型的な使われ方 – Specialization(特殊化)を行った場合、 その効果を高める – デバッガを有効化するとき、インタプリタに 遷移する Deoptimization プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 62 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int i = 1; int r = s.add(-2); if (r != 0) { ... // 長いコード } t = r + i; return t; } } r = 0 条件 r = Sub2.add(-2) -> -2 + 2 = 0 r = s.add(-2) r != 0 長いコード t = r + i インタプリタで 実行 長いコード t = r + i i = 1
  63. 63. ▪ コンパイルコード内では、rの値が0と決まるので、条件分岐と条件が成立 しない場合のコードを削除可能 ▪ コンパイルコード外に実行を移行する 際に、補償コードが必要 – コンパイラが生成した中間変数、削除した 変数、から、インタプリタ、デバッガで 参照される値の復元 – コンパイラは、i = 1を定数伝搬後、 元のiを移動する Deoptimizationによる最適化 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 63 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int i = 1; int r = s.add(-2); if (r != 0) { ... // 長いコード } t = r + i; return t; } } 条件 r = Sub2.add(-2) -> -2 + 2 = 0 r = s.add(-2) t = 0 + 1 = 1 インタプリタで 実行 i = 1 長いコード t = r + i
  64. 64. ▪ 動的型付け言語ではより効果が大きい – 単純には、各演算で型検査が必要 Deoptimizationによる効果 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 64 if (a.type == Int && b.type == Int) { int i = a.ival + b.ival; c = Int(i) } else { b = Int(1) c = add(a, b); } // cはオブジェクト b = 1 c = a + b type: INT ival: 2022 object type: INT ival: 1 object コンパイラ中間言語 コンパイル
  65. 65. ▪ 動的型付け言語ではより効果が大きい – “+”などの汎用的な演算の型を、一意に決定できる Deoptimizationによる効果 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 65 if (a.type == Int && b.type == Int) { int i = a.ival + b.ival; c = Int(i) } else { b = Int(1) c = add(a, b); } // cはオブジェクト b = 1 c = a + b type: INT ival: 2022 object type: INT ival: 1 object if (a->type == Int) { c = a.val + 1; } else { b = Int(1); goto interpreter } // cは整数の単純変数 aがintでないなら deoptimization コンパイル 1
  66. 66. ▪ 最適化されたコンパイルコードからインタプリタへの、実行遷移 – 実行時にそれぞれのコードが持つcontextの変換 ▪ r Deoptimizationの実装 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 66 if (a->type == Int) { c = a.val + 1; } else { b = Int(1); //後続で使用する変数の参照点 goto interpreter } // cは整数の単純変数 ... mov r3, object_a mov r4, object_1 コンパイルコード インタプリタ上のバイトコード 計算スタック レジスタ インタプリタの独自計算stack Local変数 レジスタ インタプリタの独自stack frame Stack frame コンパイルコードの独自stack frame (method inliningした場合、複数メソッド分が1つになっている) インタプリタの独自stack frame (各メソッドごと) 機械語命令
  67. 67. ▪ 最適化されたコンパイルコードからインタプリタへの、実行遷移 – 実行時にそれぞれのコードが持つcontextの変換 ▪ r Deoptimizationの実装 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 67 if (a->type == Int) { c = a.val + 1; } else { b = Int(1); //後続で使用する変数の参照点 goto interpreter } // cは整数の単純変数 計算stack ... mov r3, object_a mov r4, object_1 コンパイルコード インタプリタ上のバイトコード 計算スタック レジスタ インタプリタの独自計算stack Local変数 レジスタ インタプリタの独自stack Stack frame コンパイルコードの独自stack frame (method inliningした場合、複数メソッド分が1つになっている) インタプリタの独自stack (各メソッドごと) インタプリタで実行 CONST 1 int STORE b LOAD a LOAD b ADD STORE c バイトコード a 1 機械語命令 変換 r3 r4
  68. 68. ▪ インタプリタ実行中から、コンパイルコードの途中に遷移する – 一般的には、インタプリタでプログラムのループのback edgeを検出した際に、 コンパイルコードのループの先頭に移ることが多い ▪ 任意の点で移ると、実装の複雑さが増すが、得られるメリットはそれほど多くない On-Stack Replacement [Chamber1994][Kawahito2003] プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 68 int div(int i){return (i!=0) ? (4/i):0;} public static void main(String args[]) { for (int i = 0; i < 100000; i++) { int r = Super.div(2) + 3; System.println(r); } }
  69. 69. ▪ main()がインタプリタで呼び出されて、ループが何度も実行される ▪ ループのback edgeで、main()のコンパイル要求が出される On-Stack Replacementの実行例 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 69 int div(int i){return (i!=0) ? (4/i):0;} public static void main(String args[]) { for (int i = 0; i < 100000; i++) { int r = Super.div(2) + 3; System.println(r); } }
  70. 70. ▪ main() はdiv()をmethod inliningしながらコンパイルされる – メソッド先頭とループ先頭に、実行遷移点を持つコードが生成される On-Stack Replacementの実行例 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 70 int div(int i){return (i!=0) ? (4/i):0;} public static void main(String args[]) { for (int i = 0; i < 100000; i++) { int r = Super.div(2) + 3; System.println(r); } } main_entry: ... loophead: ... bne loophead ... ret main_loop_entry: ... goto loophead コンパイル 機械語命令
  71. 71. ▪ 実行遷移点では下記の変換を行う On-Stack Replacementの実行例 プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 71 int div(int i){return (i!=0) ? (4/i):0;} public static void main(String args[]) { for (int i = 0; i < 100000; i++) { int r = Super.div(2) + 3; System.println(r); } } main_entry: ... loophead: ... bne loophead ... ret main_loop_entry: ... goto loophead 機械語命令 インタプリタ上のバイトコード コンパイルコード 計算スタック インタプリタの独自計算stack レジスタ Local変数 インタプリタの独自stack frame レジスタ Stack frame インタプリタの独自stack frame コンパイルコードの独自stack frame 変換
  72. 72. 今日の授業でわかること ▪ メソッドの実行遷移の最適化 – s.add()でSub2.add()がよく呼ばれることがわかった時、”長いコード”をコンパ イルしないようにできないか?→ deoptimization – 1度だけ呼び出されるmain()メソッド内にあるSuper.div()へのメソッド呼び出 しを、実行時コンパイルでどうやってmethod inliningするか?→ OSR プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 72 class Sub2 extends Super { public int add(int i) { return i + 2; } public static int calc2(Super s) { int r = s.add(-2); if (r != 0) { ... // 長いコード } return r; } } class Super { public static final int div(int i) { return (i != 0) ? (4 / i) : 0;} public static void main(String args[]) { for (int i = 0; i < 100000; i++) { int r = Super.div(2) + 3; System.println(r); } } }
  73. 73. 今日の講義の内容のまとめ ▪ メソッド呼び出しの実行時間に関する最適化 – Method inlining ▪ 直接メソッド呼び出しにおいてInliningするメソッドの決定 – メソッド呼び出しのdevirtualization ▪ 仮想メソッド呼び出しから直接メソッド呼び出しへの変換 • Guarded devirtualization, direct devirtualization ▪ 異なるコード間の実行の遷移について – コンパイルコード ⇔ インタープリタ ▪ Deoptimization, OSR プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 73
  74. 74. 参考文献(1/2) ▪ Guarded devirtualization – Calder et al. Reducing Indirect Function Call Overhead In C++ Programs, POPL, 1994. – Grove et al. Profile-guided receiver class prediction, OOPSLA, 1995 – Holzle et al. Optimizing dynamically-typed object-oriented languages with polymorphic inline caches, ECOOP, 1991 – Arnold et al. Thin Guards: A Simple and Effective Technique for Reducing the Penalty of Dynamic Class Loading, ECOOP, 2002. ▪ 型解析 – Chambers et al. Interactive type analysis and extended message splitting; optimizing dynamically-typed object-oriented programs, PLDI, 1990. – Palsberg et al. Object-Oriented Type Inference, OOPSLA, 1991. – Gagnon et al. Efficient Inference of Static Types for Java Bytecode, SAS, 2000. – Sundaresan et al. Practical Virtual Method Call Resolution for Java, OOSPLA, 2000. – Tip et al. Scalable propagation-based call graph construction algorithms, OOSPLA, 2000. ▪ クラス階層解析 – Dean et al. Optimization of object-oriented programs using static class hierarchy, ECOOP, 1995. – Bacon et al. Fast Static Analysis of C++ Virtual Function Calls, OOPSLA, 1996. – Ishizaki et al. A Study of Devirtualization Techniques for a Java Just-In-Time Compiler, OOPSLA, 2000. – Detlefs et al. Inlining of virtual methods, ECOOP, 1999. ▪ Spilitting – Chambers et al. Interactive type analysis and extended message splitting; optimizing dynamically-typed object-oriented programs, PLDI, 1990. ▪ インタフェースメソッド呼び出し – Alpern et al. Efficient Implementation of Java Interfaces: Invokeinterface Considered Harmless, OOPSLA, 2001. ▪ 適応最適化のサーベイ論文 – Arnold et al. A Survey of Adaptive Optimization in Virtual Machines. IBM Research Report RC23143, 2003. プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 74
  75. 75. 参考文献(2/2) ▪ On stack replacement / deoptimization – Holzle et al. Debugging Optimized Code with Dynamic Deoptimization, PLDI, 1992. – Paleczny et al. The Java HotSpot Server Compiler, JVM, 2001. – Fink et al. Design, Implementation and Evaluation of Adaptive Recompilation with On-Stack Replacement, CGO, 2003. – Soman et al. Efficient and general on-stack replacement for aggressive program specialization, PLC, 2006. – Adaptive inlining and on-stack replacement in the CACAO virtual machine, PPPJ, 2007. – Lameed et al. A Modular Approach to On-Stack Replacement in LLVM, VEE, 2013. – Kedlaya et al. Deoptimization for Dynamic Language JITs on Typed, Stack-based Virtual Machines, VEE, 2014. ▪ 石崎のこれまでのスライド – https://www.slideshare.com/ishizaki/ プログラミング言語処理系の最先端実装技術 inliningとdevirtualization / Kazuaki Ishizaki 75

×