3
Bytecode DSL
& Indy
& Brainf*ck
G*Workshop Z 2013/09/20
上原潤二(NTTソフトウェア株式会社)
13年9月20日金曜日
JGGUG G*Workshop Z Copyright(C) NTT Software.
自己紹介
上原潤二(@uehaj)
NTTソフトウェア(株)Grails推進室
JGGUG(日本Grails/Groovyユーザグループ)運営委員
書籍...
JGGUG G*Workshop Z Copyright(C) NTT Software.
今日の内容
Indyの基礎
Bytecode DSL
Brainf*ckを実装してみた
G*Magazine Vol.7の宣伝
3
13年9月20日金曜日
JGGUG G*Workshop Z Copyright(C) NTT Software.
テーマ:Indyで遊びたい
Indy: Java VM上での動的言語の実行を効
率化することを目的とした一連の機能拡張
(JSR 292)
気軽でない
...
35
Bytecode DSL
13年9月20日金曜日
JGGUG G*Workshop Z Copyright(C) NTT Software.
ByteCode DSL
Groovyの内部DSLで実現されたJava
バイトコードのアセンブラ
ASMのラッパー
Indy対応! (重要)
6
@gr...
JGGUG G*Workshop Z Copyright(C) NTT Software.
BytecodeDSL
以下で@Grab可
groovyによる実行
7
@GrabResolver(name="maven-­‐repox",	
  r...
3
BytecodeDSLでHello Indy!
8
@GrabResolver(name="maven-­‐repo",	
  root="https://raw.github.com/uehaj/maven-­‐repo/gh-­‐pag...
3
実行
9
$ groovy -Dgroovy.target.bytecode=1.7 HelloIndy.groovy
Hello Indy
13年9月20日金曜日
310
Indy!!
13年9月20日金曜日
JGGUG G*Workshop Z Copyright(C) NTT Software.
Indy
Indyの動作は知ってますよね??
11
13年9月20日金曜日
3
従来のinvoke系命令のイメージ
バイトコード命令
バイトコード命令
Invokestatic/virtual/interface命令
メソッド
バイトコード命令
return命令
バイトコード命令
(1)Java VMによって解決さ
れ...
3
invokedynamic命令のイメージ
バイトコード命令
バイトコード命令
Invokedynamic命令
メソッド
バイトコード命令
return命令
バイトコード命令
(1)Java以外の言語処理系
ランタイムによって解決
される
:...
3
invokedynamicのイメージ(2)
バイトコード命令
バイトコード命令
Invokedynamic命令
バイトコード命令
:
?
(2)クラスファイル上はブートスト
ラップメソッドというメソッドに
紐付けられている
Bootstar...
3
invokedynamicのイメージ(3)
バイトコード命令
バイトコード命令
Invokedynamic命令
バイトコード命令
:
呼び出し先決定メソッド
バイトコード命令
return命令
BootStrapメソッドを指すMH
(2)B...
3
invokedynamicのイメージ(5)
バイトコード命令
バイトコード命令
Invokedynamic命令
バイトコード命令
:
CallSite
(1)invokedyamic命令にCallSiteが紐付
けられる
この結び付きはJV...
3
CallSite 呼び出し先メソッドを参照するMH
invokedynamicの最終形
バイトコード命令
バイトコード命令
メソッド
バイトコード命令
return命令
バイトコード命令
MHによるメソッド参照
:
13年9月20日金曜日
3
CallSite 呼び出し先メソッドを参照するMH
(Mutable¦Volatile)CallSite
バイトコード命令
バイトコード命令
バイトコード命令
:
(1)
メソッド1
メソッド2
×
Groovyで言うところのmetaCla...
3
Indyって結局何?
メソッド呼び出し先を間接参照を使って書き換える
しくみ
他言語メソッドの呼び出しが想定ユースケースだが技術
的にはそれに限らない(Java 8 Lambdaとか)
他言語だから、環境を持ち回したり引数をラップ・アン
ラ...
3
MHに対する高階操作
20
13年9月20日金曜日
321
Brainf*ck
13年9月20日金曜日
3
Brainf*ckをindyで実装してみた :
構成図
22
Brainf*ckソース
>+++++++++[<++++
++++>-]<.>+++++++
[<++++>-]<+.++++++
+..+++.[-]>++++++++
[<...
3
Brainf*ckとindy
静的言語だからIndyの意味ない
(MutableCallSite出番なし)
invokedynamicの引数文字列から
一連のMHを連接させたものを
BootStrapメソッドで生成してみる
23
invok...
3
MHを連接
MethodHandles#filterReturnValu
e(MH target, MH filter)
「filter(target())」を表現するMHを返す。
targetの戻り値の型がvoid、
filterの引数が無しであ...
3
CallSite 呼び出し先メソッドを参照するMH
MHを連接
バイトコード命令
バイトコード命令
メソッド(+)
バイトコード命令
return命令
バイトコード命令
:
filterReturlValueの結果得られ
る、2つのMHを呼ぶ...
3
生成コード
26
	
  static	
  void	
  main(String[]	
  args)	
  throws	
  Exception	
  {
	
  	
  	
  	
  	
  	
  	
  	
  //	
  ...
3
実行
27
% cat hello.bf
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.
[-]>++++++++[<++++>-]<.>+++++++++++[<+++...
3
まとめ
Indyは面白い
G*Magazine Vol7乞う期待!
28
13年9月20日金曜日
Upcoming SlideShare
Loading in …5
×

Indy(Invokedynamic) and Bytecode DSL and Brainf*ck

2,388 views

Published on

implement Brainf*ck compiler using Indy with BytecodeDSL.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,388
On SlideShare
0
From Embeds
0
Number of Embeds
1,141
Actions
Shares
0
Downloads
4
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Indy(Invokedynamic) and Bytecode DSL and Brainf*ck

  1. 1. 3 Bytecode DSL & Indy & Brainf*ck G*Workshop Z 2013/09/20 上原潤二(NTTソフトウェア株式会社) 13年9月20日金曜日
  2. 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. 3. JGGUG G*Workshop Z Copyright(C) NTT Software. 今日の内容 Indyの基礎 Bytecode DSL Brainf*ckを実装してみた G*Magazine Vol.7の宣伝 3 13年9月20日金曜日
  4. 4. JGGUG G*Workshop Z Copyright(C) NTT Software. テーマ:Indyで遊びたい Indy: Java VM上での動的言語の実行を効 率化することを目的とした一連の機能拡張 (JSR 292) 気軽でない ASM面倒くさい ByteCode DSLを使おう! 4 13年9月20日金曜日
  5. 5. 35 Bytecode DSL 13年9月20日金曜日
  6. 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. 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. 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. 9. 3 実行 9 $ groovy -Dgroovy.target.bytecode=1.7 HelloIndy.groovy Hello Indy 13年9月20日金曜日
  10. 10. 310 Indy!! 13年9月20日金曜日
  11. 11. JGGUG G*Workshop Z Copyright(C) NTT Software. Indy Indyの動作は知ってますよね?? 11 13年9月20日金曜日
  12. 12. 3 従来のinvoke系命令のイメージ バイトコード命令 バイトコード命令 Invokestatic/virtual/interface命令 メソッド バイトコード命令 return命令 バイトコード命令 (1)Java VMによって解決さ れて呼び出される : 13年9月20日金曜日
  13. 13. 3 invokedynamic命令のイメージ バイトコード命令 バイトコード命令 Invokedynamic命令 メソッド バイトコード命令 return命令 バイトコード命令 (1)Java以外の言語処理系 ランタイムによって解決 される : 13年9月20日金曜日
  14. 14. 3 invokedynamicのイメージ(2) バイトコード命令 バイトコード命令 Invokedynamic命令 バイトコード命令 : ? (2)クラスファイル上はブートスト ラップメソッドというメソッドに 紐付けられている Bootstarpメソッド バイトコード命令 return命令 (1)クラスロード時には未定 13年9月20日金曜日
  15. 15. 3 invokedynamicのイメージ(3) バイトコード命令 バイトコード命令 Invokedynamic命令 バイトコード命令 : 呼び出し先決定メソッド バイトコード命令 return命令 BootStrapメソッドを指すMH (2)BootstrapメソッドはCallSiteオブジ ェクトを返す CallSite 呼び出し先メソッ ドを参照するMH (1)BootStrapメソッドを示す MH(MethodHandle)で表現されている 13年9月20日金曜日
  16. 16. 3 invokedynamicのイメージ(5) バイトコード命令 バイトコード命令 Invokedynamic命令 バイトコード命令 : CallSite (1)invokedyamic命令にCallSiteが紐付 けられる この結び付きはJVMの実行を通じて以後不可逆、不変なので、以下のようにinvokedynamic がCallSiteに置き変わると考えても良いかも知れない。 (※CallSiteオブジェクトは複数の invokedynamic命令でシェアされ得る点でこのイメージは正確ではない。) バイトコード命令 バイトコード命令 CallSite バイトコード命令 呼び出し先メソッドを参照するMH 呼び出し先メソッ ドを参照するMH 13年9月20日金曜日
  17. 17. 3 CallSite 呼び出し先メソッドを参照するMH invokedynamicの最終形 バイトコード命令 バイトコード命令 メソッド バイトコード命令 return命令 バイトコード命令 MHによるメソッド参照 : 13年9月20日金曜日
  18. 18. 3 CallSite 呼び出し先メソッドを参照するMH (Mutable¦Volatile)CallSite バイトコード命令 バイトコード命令 バイトコード命令 : (1) メソッド1 メソッド2 × Groovyで言うところのmetaClassの変更のタイミングで実際のメソッドの差し替え を行なうことができるCallSiteもある。(これがキモ) 結局、「ポインタを解した呼び出し先アドレスの間接参照」を オブジェクト指向的に、型安全に行なっている。 13年9月20日金曜日
  19. 19. 3 Indyって結局何? メソッド呼び出し先を間接参照を使って書き換える しくみ 他言語メソッドの呼び出しが想定ユースケースだが技術 的にはそれに限らない(Java 8 Lambdaとか) 他言語だから、環境を持ち回したり引数をラップ・アン ラップする処理が必要になる場合がある メソッド呼び出しに伴なう前後処理(MHに対する高階 操作:後述)をJVM管理下で構成・実行するしくみがあ ることがメリット ➡最適化(インライン展開)期待 ➡そういう前後処理が不要な場合、速度メリットがあるかは?? ※ 「MH呼び出しは速い」は都市伝説 19 13年9月20日金曜日
  20. 20. 3 MHに対する高階操作 20 13年9月20日金曜日
  21. 21. 321 Brainf*ck 13年9月20日金曜日
  22. 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. 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. 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. 25. 3 CallSite 呼び出し先メソッドを参照するMH MHを連接 バイトコード命令 バイトコード命令 メソッド(+) バイトコード命令 return命令 バイトコード命令 : filterReturlValueの結果得られ る、2つのMHを呼ぶMH filterReturlValueの結果得られ る、2つのMHを呼ぶMH メソッド(+) バイトコード命令 return命令 メソッド(>) バイトコード命令 return命令 13年9月20日金曜日
  26. 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. 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. 28. 3 まとめ Indyは面白い G*Magazine Vol7乞う期待! 28 13年9月20日金曜日

×