Submit Search
Indy(Invokedynamic) and Bytecode DSL and Brainf*ck
•
3 likes
•
3,213 views
U
Uehara Junji
Follow
implement Brainf*ck compiler using Indy with BytecodeDSL.
Read less
Read more
1 of 28
Download now
Download to read offline
More Related Content
Indy(Invokedynamic) and Bytecode DSL and Brainf*ck
1.
3 Bytecode DSL & Indy &
Brainf*ck G*Workshop Z 2013/09/20 上原潤二(NTTソフトウェア株式会社) 13年9月20日金曜日
2.
JGGUG G*Workshop Z
Copyright(C) NTT Software. 自己紹介 上原潤二(@uehaj) NTTソフトウェア(株)Grails推進室 JGGUG(日本Grails/Groovyユーザグループ)運営委員 書籍: プログラミングGROOVY(技術評論社) Grails徹底入門(翔泳社) ブログ「Grな日々」 GroovyServ, LispBuilder, GVM(JVM written in Groovy)開発者 2 13年9月20日金曜日
3.
JGGUG G*Workshop Z
Copyright(C) NTT Software. 今日の内容 Indyの基礎 Bytecode DSL Brainf*ckを実装してみた G*Magazine Vol.7の宣伝 3 13年9月20日金曜日
4.
JGGUG G*Workshop Z
Copyright(C) NTT Software. テーマ:Indyで遊びたい Indy: Java VM上での動的言語の実行を効 率化することを目的とした一連の機能拡張 (JSR 292) 気軽でない ASM面倒くさい ByteCode DSLを使おう! 4 13年9月20日金曜日
5.
35 Bytecode DSL 13年9月20日金曜日
6.
JGGUG G*Workshop Z
Copyright(C) NTT Software. ByteCode DSL Groovyの内部DSLで実現されたJava バイトコードのアセンブラ ASMのラッパー Indy対応! (重要) 6 @groovyx.ast.bytecode.Bytecode int fib(int i) { iload 1 iconst_2 if_icmpge l1 iload 1 _goto l2 l1 aload 0 iload 1 iconst_2 isub invokevirtual '.fib', '(I)I' aload 0 iload 1 iconst_1 isub invokevirtual '.fib' ,'(I)I' iadd l2 ireturn } 13年9月20日金曜日
7.
JGGUG G*Workshop Z
Copyright(C) NTT Software. BytecodeDSL 以下で@Grab可 groovyによる実行 7 @GrabResolver(name="maven-‐repox", root = "https:// raw.github.com/uehaj/maven-‐repo/gh-‐pages/snapshot") @Grab('groovyx.ast.bytecode:groovy-‐bytecode-‐ast:0.2.0-‐ separate-‐asm') import groovyx.ast.bytecode.Bytecode $ groovy fib.groovy 102334155 13年9月20日金曜日
8.
3 BytecodeDSLでHello Indy! 8 @GrabResolver(name="maven-‐repo", root="https://raw.github.com/uehaj/maven-‐repo/gh-‐pages/snapshot") @Grab("groovyx.ast.bytecode:groovy-‐bytecode-‐ast:0.2.0-‐separate-‐asm") import
groovyx.ast.bytecode.Bytecode import java.lang.invoke.* import java.lang.invoke.MethodHandles.Lookup import static org.objectweb.asm.Opcodes.H_INVOKESTATIC class HelloIndy { public static CallSite bootstrap(Lookup lookup, String methodName, MethodType type) { assert methodName == 'xx' MethodHandle mh = lookup.findVirtual(java.io.PrintStream, "println", MethodType.methodType(void,[String])) return new ConstantCallSite(mh) } @Bytecode static main(args) { getstatic 'java/lang/System.out','Ljava/io/PrintStream;' ldc 'Hello Indy' invokedynamic 'xx', '(Ljava/io/PrintStream;Ljava/lang/ String;)V', [H_INVOKESTATIC, 'HelloIndy','bootstrap', [CallSite, Lookup, String, MethodType]] vreturn } } 13年9月20日金曜日
9.
3 実行 9 $ groovy -Dgroovy.target.bytecode=1.7
HelloIndy.groovy Hello Indy 13年9月20日金曜日
10.
310 Indy!! 13年9月20日金曜日
11.
JGGUG G*Workshop Z
Copyright(C) NTT Software. Indy Indyの動作は知ってますよね?? 11 13年9月20日金曜日
12.
3 従来のinvoke系命令のイメージ バイトコード命令 バイトコード命令 Invokestatic/virtual/interface命令 メソッド バイトコード命令 return命令 バイトコード命令 (1)Java VMによって解決さ れて呼び出される : 13年9月20日金曜日
13.
3 invokedynamic命令のイメージ バイトコード命令 バイトコード命令 Invokedynamic命令 メソッド バイトコード命令 return命令 バイトコード命令 (1)Java以外の言語処理系 ランタイムによって解決 される : 13年9月20日金曜日
14.
3 invokedynamicのイメージ(2) バイトコード命令 バイトコード命令 Invokedynamic命令 バイトコード命令 : ? (2)クラスファイル上はブートスト ラップメソッドというメソッドに 紐付けられている Bootstarpメソッド バイトコード命令 return命令 (1)クラスロード時には未定 13年9月20日金曜日
15.
3 invokedynamicのイメージ(3) バイトコード命令 バイトコード命令 Invokedynamic命令 バイトコード命令 : 呼び出し先決定メソッド バイトコード命令 return命令 BootStrapメソッドを指すMH (2)BootstrapメソッドはCallSiteオブジ ェクトを返す CallSite 呼び出し先メソッ ドを参照するMH (1)BootStrapメソッドを示す MH(MethodHandle)で表現されている 13年9月20日金曜日
16.
3 invokedynamicのイメージ(5) バイトコード命令 バイトコード命令 Invokedynamic命令 バイトコード命令 : CallSite (1)invokedyamic命令にCallSiteが紐付 けられる この結び付きはJVMの実行を通じて以後不可逆、不変なので、以下のようにinvokedynamic がCallSiteに置き変わると考えても良いかも知れない。 (※CallSiteオブジェクトは複数の invokedynamic命令でシェアされ得る点でこのイメージは正確ではない。) バイトコード命令 バイトコード命令 CallSite バイトコード命令 呼び出し先メソッドを参照するMH 呼び出し先メソッ ドを参照するMH 13年9月20日金曜日
17.
3 CallSite 呼び出し先メソッドを参照するMH invokedynamicの最終形 バイトコード命令 バイトコード命令 メソッド バイトコード命令 return命令 バイトコード命令 MHによるメソッド参照 : 13年9月20日金曜日
18.
3 CallSite 呼び出し先メソッドを参照するMH (Mutable¦Volatile)CallSite バイトコード命令 バイトコード命令 バイトコード命令 : (1) メソッド1 メソッド2 × Groovyで言うところのmetaClassの変更のタイミングで実際のメソッドの差し替え を行なうことができるCallSiteもある。(これがキモ) 結局、「ポインタを解した呼び出し先アドレスの間接参照」を オブジェクト指向的に、型安全に行なっている。 13年9月20日金曜日
19.
3 Indyって結局何? メソッド呼び出し先を間接参照を使って書き換える しくみ 他言語メソッドの呼び出しが想定ユースケースだが技術 的にはそれに限らない(Java 8 Lambdaとか) 他言語だから、環境を持ち回したり引数をラップ・アン ラップする処理が必要になる場合がある メソッド呼び出しに伴なう前後処理(MHに対する高階 操作:後述)をJVM管理下で構成・実行するしくみがあ ることがメリット ➡最適化(インライン展開)期待 ➡そういう前後処理が不要な場合、速度メリットがあるかは?? ※
「MH呼び出しは速い」は都市伝説 19 13年9月20日金曜日
20.
3 MHに対する高階操作 20 13年9月20日金曜日
21.
321 Brainf*ck 13年9月20日金曜日
22.
3 Brainf*ckをindyで実装してみた : 構成図 22 Brainf*ckソース >+++++++++[<++++ ++++>-]<.>+++++++ [<++++>-]<+.++++++ +..+++.[-]>++++++++ [<++++>-]<.>++++++ +++++[<+++++>-]<.> ++++++++[<+++>-]<. +++.------.--------.[-]>+ +++++++[<++++>-]< +.[-]++++++++++. compile. groovy https://gist.github.com/uehaj/6614136 https://gist.github.com/uehaj/6614447 Brainf*ckコンパイラ 生成コード(Bytecode DSL/indyを使用) groovy groovy “hello world” JVM JVM(Java7) a.groovy 13年9月20日金曜日
23.
3 Brainf*ckとindy 静的言語だからIndyの意味ない (MutableCallSite出番なし) invokedynamicの引数文字列から 一連のMHを連接させたものを BootStrapメソッドで生成してみる 23 invokedynamic 'dummy', '()V',
[H_INVOKESTATIC, 'Brainfuck', 'bootstrap', [CallSite, Lookup, String, MethodType, String]], '>++++++++' 13年9月20日金曜日
24.
3 MHを連接 MethodHandles#filterReturnValu e(MH target, MH
filter) 「filter(target())」を表現するMHを返す。 targetの戻り値の型がvoid、 filterの引数が無しであれば、単にtarget, filterの順にMHを呼び出す filterReternValueの結果を filterReturnValueに与えることで任意個数 のMHを逐次実行できる 24 13年9月20日金曜日
25.
3 CallSite 呼び出し先メソッドを参照するMH MHを連接 バイトコード命令 バイトコード命令 メソッド(+) バイトコード命令 return命令 バイトコード命令 : filterReturlValueの結果得られ る、2つのMHを呼ぶMH filterReturlValueの結果得られ る、2つのMHを呼ぶMH メソッド(+) バイトコード命令 return命令 メソッド(>) バイトコード命令 return命令 13年9月20日金曜日
26.
3 生成コード 26 static void
main(String[] args) throws Exception { // Brainfuckからコンバートされたコード invokedynamic 'dummy', '()V', ... '>+++++++++' _GOTO tmp1 lab1: invokedynamic 'dummy', '()V', ... '<++++++++>-‐' tmp1: getstatic '.data','[B' getstatic '.dp','I' baload ifne lab1 invokedynamic 'dummy', '()V', ... '<.>+++++++' _GOTO tmp2 lab2: invokedynamic 'dummy', '()V', .... '<++++>-‐' tmp2: getstatic '.data','[B' getstatic '.dp','I' baload ifne lab2 invokedynamic 'dummy', '()V', .... '<+.+++++++..+ ++.' _GOTO tmp3 lab3: : >+++++++++ [ <++++++++>- ] <.>+++++++ [ <++++>- ] <+.+++++++..+++. 13年9月20日金曜日
27.
3 実行 27 % cat hello.bf >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++. [-]>++++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+ ++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]+++++ +++++. %
groovy compile.groovy hello.bf > a.groovy % groovy -Dgroovy.target.bytecode=1.7 a.groovy Hello World! 13年9月20日金曜日
28.
3 まとめ Indyは面白い G*Magazine Vol7乞う期待! 28 13年9月20日金曜日
Download