kink: invokedynamic on a prototype-based language

24
Kink: プロトタイプベース言語で invokedynamic (構想) @miyakawa_taku 2012-02-22 JJUG Night Seminar

Upload: taku-miyakawa

Post on 13-Jul-2015

683 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Kink: invokedynamic on a prototype-based language

Kink: プロトタイプベース言語での invokedynamic (構想)

@miyakawa_taku

2012-02-22

JJUG Night Seminar

Page 2: Kink: invokedynamic on a prototype-based language

要旨

• Kink という JVM 言語を作っています

• JavaScript や Lua と同様に、クラスのないオブジェクト指向言語です

• invokedynamic がどこに使えるものか考えてみました

1

Page 3: Kink: invokedynamic on a prototype-based language

論点

• Kink の紹介

– クラスのない世界

–なんでもメソッド

–気になる性能は?

• invokedynamic の使い所

–スロットアクセスの最適化

– SwitchPoint で実行モード切り替え

2

Page 4: Kink: invokedynamic on a prototype-based language

論点

• Kink の紹介

– クラスのない世界

–なんでもメソッド

–気になる性能は?

• invokedynamic の使い所

–スロットアクセスの最適化

– SwitchPoint で実行モード切り替え

3

Page 5: Kink: invokedynamic on a prototype-based language

クラスのない世界

• クラスはなく値だけがある

• データもメソッドもいきなり値のスロット (≒フィールド) に突っ込む

&DOG = value DOG.&bark = { 'Bow!' } printline(DOG.bark) # => Bow!

4

Page 6: Kink: invokedynamic on a prototype-based language

クラスのかわりに親

• 自分自身がスロットを持っていなかったら親から取ってくる

• 親のことをプロトタイプとも言う

&PROTODOG = value('bark' : { 'Bow!' }) &DOG = PROTODOG.child printline(DOG.bark) # => Bow!

5

Page 7: Kink: invokedynamic on a prototype-based language

親/子関係の一つ覚え

• つまり子は親の名前空間を継承する

• 様々な仕組みを親/子関係で実現する

– クラス / インスタンス (のようなもの)

–親クラス / 子クラス (のようなもの)

–外側のスコープ / 内側のスコープ

6

Page 8: Kink: invokedynamic on a prototype-based language

なんでもメソッド

• 足し算も掛け算もメソッド

• 条件分岐もメソッド

• 代入もメソッド

• 引数渡しもメソッド

7

Page 9: Kink: invokedynamic on a prototype-based language

足し算も掛け算もメソッド

• 演算子はメソッドの構文糖

(TOP + BOTTOM) * HEIGHT

TOP.plus(BOTTOM).multiply(HEIGHT)

8

Page 10: Kink: invokedynamic on a prototype-based language

条件分岐もメソッド

• if-then-else は bool 値のメソッド

(N % 2 == 0).then { 'even' } { 'odd' }

(N % 2 == 0).then({ 'even' } { 'odd' })

9

Page 11: Kink: invokedynamic on a prototype-based language

代入もメソッド

• スロットへの代入はスロットのメソッド

&NUM = 42

&NUM.assign(42)

10

Page 12: Kink: invokedynamic on a prototype-based language

引数渡しもメソッド

• 引数渡しは仮引数列 (スロットのリスト) のメソッド

&diff = { (&X &Y) X - Y }

&diff = { [&X &Y] = _args X - Y }

11

Page 13: Kink: invokedynamic on a prototype-based language

気になる性能は?

• tarai(13 6 0) (たらい回し関数、竹内関数) で マイクロベンチマーク

&tarai = { (&X &Y &Z) (X <= Y).then { Y } { tarai(tarai(X - 1 Y Z) tarai(Y - 1 Z X) tarai(Z - 1 X Y)) } } printline(tarai(~ argv.map { __.int }))

12

Page 14: Kink: invokedynamic on a prototype-based language

結果: bc よりは速い

0 20 40 60 80 100 120 140 160

JRuby 1.6.6

Groovy 1.7.0

Lua 5.0.3

C Ruby 1.9.2

mawk 1.3.3

Python 2.6.6

scm 5e5

C Ruby 1.8.7

Kink 2012-02-19

GNU bc 1.06.95

13

Page 15: Kink: invokedynamic on a prototype-based language

つまりこんな言語

• クラスがなくて値だけがある

• 代入も制御構造もメソッド呼び出し

• 速くするのはかなり難渋する

• あと、末尾呼び出しでスタックオーバーフローが起きないことを保証しています

14

Page 16: Kink: invokedynamic on a prototype-based language

論点

• Kink の紹介

– クラスのない世界

–なんでもメソッド

–気になる性能は?

• invokedynamic の使い所

–スロットアクセスの最適化

– SwitchPoint で実行モード切り替え

15

Page 17: Kink: invokedynamic on a prototype-based language

処理系の作り

• プログラムはJVM バイトコードにせず、「評価器」を作って実行する (cf. SICP 4章)

&loop.do { print("twift!") loop }

call

slot proc

chunk

抽象構文木

call

slot proc

chunk

評価器 プログラム

16

Page 18: Kink: invokedynamic on a prototype-based language

invokedynamic の使い所

• そもそもJVM バイトコードにしないので、メソッド呼び出しがいきなり invokedynamic になることはない

• ただし、高速化のためにバイトコード生成を使っている所はあって、そこに invokedynamic が使えるかも

17

Page 19: Kink: invokedynamic on a prototype-based language

スロットアクセスの最適化

• スロットアクセスを速くするため、スロット集合のクラスを実行時に生成している

• 本来はアクセス元のコードでキャッシュを効かせて速くする (現在は未実装)

• ここに invokedynamic が使えそう

DOG

bark { "Bow!" }

jump { "Pong!" }

DOG.bark

ここに使う

18

Page 20: Kink: invokedynamic on a prototype-based language

if (slots.getClass() == #cachedClass) { return ((#cachedClass) slots).bar; } else { deoptimize(); return slots.get("bar"); }

スロットアクセスの最適化

• キャッシュヒット → フィールドを直接取得

• キャッシュミス → フォールバック

• MethodHandles#guardWithTest が使えそう

test

target

fallback

19

Page 21: Kink: invokedynamic on a prototype-based language

SwitchPoint で実行モード切り替え

• スロットやリストへの代入はメソッド呼び出し

• 毎回メソッドを呼ぶと大変なコストなので、可能な限りショートカット処理している

• ここで SwitchPoint#guardWithTest が使えそう

20

if 代入メソッドは再定義されていない? ショートカット処理 else 真面目にメソッド呼び出し

Page 22: Kink: invokedynamic on a prototype-based language

SwitchPoint で実行モード切り替え

• SwitchPoint は MethodHandle のファクトリ

– SP.guardWithTest(target, fallback):MethodHandle

–通常は target が実行される

– SwitchPoint が invalidate されると、それ以降は fallback が実行される

• 処理の実行モードを切り替えるのに使える

–代入処理の MH を SwitchPoint で生成

–代入メソッドが再定義されたら invalidate

21

Page 23: Kink: invokedynamic on a prototype-based language

invokedynamic の使い所 (rep)

• クラスのない言語でも充分使い所はある

–スロットアクセスの最適化

–実行モード切り替え

22

Page 24: Kink: invokedynamic on a prototype-based language

参考

• Kink Programming Language

– http://code.google.com/p/kink-lang/

• V8 JavaScript Engine

– http://code.google.com/p/v8/

–スロットアクセスを最適化する仕組みのパクリ元 (Hidden Class)

• An efficient implementation of SELF

– http://dl.acm.org/citation.cfm?id=74884

23