Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう

3,550 views

Published on

2019-02-27(水)【東京】 JJUGナイトセミナー「JVM言語を作ろう! GraalVMで遊ぼう!」のセッション資料です。

阪田 浩一 (@jyukutyo): ポノス株式会社 / 関西Javaエンジニアの会 / Javaチャンピオン

オラクル社からGraalVMというものが発表され、話題を呼んでいます。GraalVMは、HotSpot VM上に新しいJITコンパイラGraalと、言語実装用フレームワーク/ASTインタプリタであるTruffle、ネイティブイメージ作成機能とその実行に使われるSubstrateVMを併せ持ったものです。すでに、Truffleを使用したJavaScriptやRuby、R、Pythonの実装がGraalVMにあり、これらの言語とJavaは、コードから"相互に"呼び出しができます。独自の言語も、ASTにさえできれば、Truffleを使い、JVM上で実行できるよう実装できます。私も、簡単な四則演算の言語を、Truffleを使って実装したことがあります。Truffleは、Graal上で動作するものです。Graalには、こうして複数の言語を相互運用する際に、高いパフォーマンスを出せるよう、機能が実装されています。

このセッションでは、TruffleとGraalの概要と、言語を実行する際に、この2つがどのような働きをするか、を主に解説します。私もTruffleを使って、言語を実装してみようかな、と思っていただくことがゴールのセッションです。

Published in: Technology
  • Be the first to comment

GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう

  1. 1. 阪田 浩一 Koichi Sakata GraalVMで使われている、 他言語をJVM上に実装する 仕組みを学ぼう
  2. 2. About Me • 阪田 浩一 @jyukutyo • 関西Javaエンジニアの会 会長 • Javaチャンピオン • ポノス株式会社(京都) • JVMになりたい人
  3. 3. http://www.graalvm.org/
  4. 4. http://www.graalvm.org/
  5. 5. WIP for Windows
  6. 6. GraalVM = HotSpotVM + α
  7. 7. Custom Part in GraalVM • Graal – JIT Compiler • Truffle – Language Implementation Framework • SubstrateVM – Runtime Library andTools for Java AOT Compiled Code
  8. 8. HotSpotVM Compiler Interface C2C1 HotSpotVM C++
  9. 9. GraalVM Compiler Interface GraalC1 HotSpotVM JVMCI Java
  10. 10. GraalVM ≠ Graal
  11. 11. Top 10ThingsTo DoWith GraalVM 1. High-performance modern Java 2. Low-footprint, fast-startup Java 3. Combine JavaScript, Java, Ruby, and R 4. Run native languages on the JVM 5. Tools that work across all languages 6. Extend a JVM-based application 7. Extend a native application 8. Java code as a native library 9. Polyglot in the database 10. Create your own language
  12. 12. http://www.graalvm.org/
  13. 13. Top 10ThingsTo DoWith GraalVM 1. High-performance modern Java 2. Low-footprint, fast-startup Java 3. Combine JavaScript, Java, Ruby, and R 4. Run native languages on the JVM 5. Tools that work across all languages 6. Extend a JVM-based application 7. Extend a native application 8. Java code as a native library 9. Polyglot in the database 10. Create your own language
  14. 14. Polyglot HotSpotVM JVMCI Graal JVM lang Truffle LLVMJS R Ruby C C++ Fortran
  15. 15. Polyglot HotSpotVM JVMCI Graal JVM lang Truffle LLVMJS R Ruby C C++ Fortran Interpreter
  16. 16. Truffleでの言語実装 • TruffleRuby (Ruby) – https://github.com/graalvm/truffleruby • FastR (GNU R) – https://github.com/graalvm/fastr • Graal.js (JavaScript) – ECMAScript 2018/Node.js 10.15.0 – https://github.com/graalvm/graaljs • SimpleLanguage (学習用) – https://github.com/graalvm/simplelanguage
  17. 17. ということは…!
  18. 18. オレオレ言語もJVM上で! HotSpotVM JVMCI Graal JVM lang Truffle オレオレ言語
  19. 19. なんでそんなことするの? Because it's fun!
  20. 20. 今日のゴール 私もTruffleを使って、 言語を実装してみようかな、 と思ってもらうこと
  21. 21. Truffle • Language Implementation Framework – A library for building programming language implementations as interpreters for AST
  22. 22. AST Abstract SyntaxTree 抽象構文木
  23. 23. サンプルとして 四則演算を考える
  24. 24. AST * 3 1 2 +(1 + 2) * 3
  25. 25. プログラムを ASTに変換する とは
  26. 26. プログラムの解析 (1 + 2) * 3 ( 1 + 2 ) * 3 レキサー パーサー
  27. 27. サンプル (1 + 2) * 3 ( 1 + 2 ) * 3 テキスト トークン 構文木
  28. 28. ASTへ * 3 1 2 +
  29. 29. ASTを インタープリトして コードを実行する
  30. 30. Truffleのメリット ASTにさえできれば、 GraalとJVMに 実行を任せられる
  31. 31. Truffleでのメリット ランタイム構築を 自分でやらなくてよい
  32. 32. たとえば JITコンパイル (Partial Evaluation/部分評価)
  33. 33. モジュール 入力 出力 レキサー (字句解析) テキスト (コード) トークン パーサー (構文解析) トークン 構文木 AST インタプリタ 構文木から作成した AST 実行結果 プログラムを実行するまで
  34. 34. モジュール 入力 出力 レキサー (字句解析) テキスト (コード) トークン パーサー (構文解析) トークン 構文木 AST インタプリタ 構文木から作成した AST 実行結果 プログラムを実行するまで今日の範囲外
  35. 35. レキサー/パーサー • ANTLR http://www.antlr.org/
  36. 36. モジュール ライブラリ レキサー ANTLR パーサー ANTLR ASTインタプリタ Truffle ライブラリの役割
  37. 37. 今日の内容 オレオレ言語のコードを ASTに変換した前提で、 そのASTをTruffleを使って JVM上で実行させる
  38. 38. 今日のソースコード • Truffle 1.0.0 RC12対応 – https://github.com/jyukutyo/JVM-Math-Language
  39. 39. Truffle • トラフル(トリュフ) • 言語実装用フレームワーク – ASTインタプリタ構築の基盤を提供する • Graalプロジェクトの一部 – Oracle Labs主導 – https://github.com/graalvm/graal/tree/master/truffle
  40. 40. Truffleでの言語実装 1. AST用ノードクラスを作成 2. Truffleの言語実装に必須のクラスを実装 3. (入出力などの実装)
  41. 41. Truffleでの言語実装 1. AST用ノードクラスを作成 2. 3.
  42. 42. 再度 四則演算
  43. 43. 四則演算でのノード • 数値ノード(子ノード:なし) – BigDecimal – Long(BigDecimalだけでもよいが、あえて) • 演算子ノード(子ノード:オペランド2つ) – Add(+) – Subtract(-) – Multiply(*) – Divide(/) • 括弧ノード "-1"といった 書き方はサポートしない
  44. 44. 今回のノード RootNode MulNode ParenNode LongNode LongNode LongNode AddNode
  45. 45. ノードのクラス図 全ノードの スーパークラス
  46. 46. ノードのクラス図 かっこに対応する ノード
  47. 47. 演算子ノードのクラス図
  48. 48. Truffleのノードクラス • Truffle DSL APIを使う 1. 提供されるアノテーションを 実装コードに付与する 2. Truffleのアノテーションプロセッサが コードを生成する
  49. 49. アノテーションの種類、意味は Javadocを読むしかない (ドキュメントは整備されていない)
  50. 50. (なお、アノテーションで、 JITコンパイルにおける 部分評価の範囲なども 設定できる)
  51. 51. 数値ノード @NodeInfo(shortName = "const") public class LongNode extends JvmMathLangNode { private final long value; public LongNode(long l) { this.value = l; } public long executeLong(VirtualFrame frame) { return this.value; } @Override public Object executeGeneric(VirtualFrame frame) { return this.value; } }
  52. 52. 加算ノード @NodeInfo(shortName = "+") public abstract class AddNode extends BinaryNode { @Specialization(rewriteOn = ArithmeticException.class) @TruffleBoundary protected long add(long left, long right) { return Math.addExact(left, right); } @Specialization @TruffleBoundary protected BigDecimal add(BigDecimal left, BigDecimal right) { return left.add(right); }
  53. 53. BinaryNode @NodeChildren({ @NodeChild("leftNode"), @NodeChild("righrNode") }) public abstract class BinaryNode extends JvmMathLangNode { }
  54. 54. 子ノードを持つノード (演算子ノードなど) の実際の処理は、 アノテーションプロセッサが 自動生成する
  55. 55. ノードのクラス図 Truffleのアノテーションプロセッサが生成する
  56. 56. 自動生成コードを 見ましょう
  57. 57. Truffleでの言語実装 1. 2. Truffleの言語実装に必須のクラスを実装 3.
  58. 58. 言語を定める クラスを作る
  59. 59. com.oracle.truffle.api. TruffleLanguageクラス を継承して実装する
  60. 60. CallTarget parse(ParsingRequest r) 実装する必要があるのは この1メソッドのみ
  61. 61. CallTarget parse(ParsingRequest r) Truffleのエンジンが このメソッドを 呼び出す
  62. 62. クラス 説明 ParsingRequest getSource()で 実行するプログラムを取得する CallTarget Truffle.getRuntime() .createCallTarget(RootNode)で生 成できる CallTarget parse(ParsingRequest r)
  63. 63. 言語規定クラス @TruffleLanguage.Registration(id = "jvmmathlang", name = "JVM Math Language", version = "0.0.2") public class JvmMathLang extends TruffleLanguage<JvmMathLangContext> { @Override protected CallTarget parse(ParsingRequest r) throws Exception { JvmMathLangRootNode main = parseSource(r.getSource()); return Truffle.getRuntime().createCallTarget(main); }
  64. 64. parseSource()内で、 字句解析、構文解析、 AST構築をする
  65. 65. parseSource()を 見ましょう
  66. 66. Truffleでの言語実装 1. 2. 3. (入出力などの実装)
  67. 67. 入出力 実行したいプログラムを Truffleのエンジンに どのように渡し、 結果をどのように 受け取るか?
  68. 68. メインクラス public class JvmMathLangMain { public static void main(String[] args) throws IOException { Context context = Context.create("jvmmathlang"); Object answer = runCode(context, [PROGRAM_FOR_RUN]); } private static Object runCode(Context context, String program) throws IOException { Source source = Source.newBuilder("jvmmathlang", program, "MATH").build(); Value value = context.eval(source); return value; } }
  69. 69. Context#eval(Source)すると CallTarget parse(ParsingRequest) を経由してプログラムが実行され、 結果がValueインスタンスで返ってくる
  70. 70. 実行 • TruffleのJARファイルを追加して、HotSpot VM上でも実行可能 – なお、Java 10から、Graalはデフォルトで 入っている(Experimental) • GraalVM上でも実行可能 – Truffle言語をGraalVMで動かす - きしだのHatena • http://nowokay.hatenablog.com/entry/20190104/1546620114
  71. 71. よりTruffleを学ぶには • コードを読むしかありません
  72. 72. まとめ Truffleで、 あなたもオレオレ言語を JVM上で実行できる!
  73. 73. Truffle言語には Interoperability がある
  74. 74. 単体の言語を 高パフォーマンスに 実行できるだけではない
  75. 75. 例) JavaScriptコードから Rubyコードを “低コスト”で呼び出せる
  76. 76. JavaScriptからRuby js>vararray= Polyglot.eval("ruby","[1,2,42,4]") js> array[2] 42 [GRAALVM_HOME]/bin/polyglot --shell --jvm https://www.sakatakoichi.com/entry/graalvmpolyglot
  77. 77. Chromeでのデバッグ
  78. 78. Graal &Truffle • Graalは言語実装そのものは知らない – Truffleを間に挟んでいる(JVM言語以外) • JITコンパイルでは(結果として) 複数言語にまたがったコンパイルができる
  79. 79. call call call many times
  80. 80. call call
  81. 81. 今日のソースコード • Truffle 1.0.0 RC12対応 – https://github.com/jyukutyo/JVM-Math-Language
  82. 82. ThankYou for Coming!
  83. 83. ANTLRの書籍
  84. 84. 加算ノード @NodeInfo(shortName = "+") public abstract class AddNode extends BinaryNode { @Specialization @TruffleBoundary protected BigDecimalTruffleObject add(Object left, Object right) { BigDecimal l = left instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) left).getValue() : BigDecimal.valueOf((long) left); BigDecimal r = right instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) right).getValue() : BigDecimal.valueOf((long) right); return new BigDecimalTruffleObject(l.add(r)); } }

×