41
プログラミング言語処理系論 (9) Design and Implementation of Programming Language Processors 佐藤周行 (情報基盤センター/電気系専攻融合情報学 コース)

プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

プログラミング言語処理系論 (9) Design and Implementation of Programming Language Processors

佐藤周行

(情報基盤センター/電気系専攻融合情報学コース)

Page 2: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

今日の予定

Parrot設計の実際

最適化について

Page 3: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

JVMで十分か?

(問題11)次の論文のうち、どれかを読み、要約せよ

1. JVM-hosted languages: they talk the talk, but do they walk the walk?

W. Li, D. White, J. Singer, PPPJ’13, 2013.

2. Characteristics of dynamic JVM languages

A. Sarimbekov et.al., VMIL’13, 2013.

Page 4: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

parrot.org/

Page 5: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Register Machine

Register Machine

各種演算のオペランドにレジスタ(変数)を想定する

ハードウェア命令との親和性が高いと主張する

ハードウェアとの親和性を考えるとき、命令体系のレジスタセットとハードウェアのレジスタセットが異なる場合、「Register Allocation」が必要になる

レジスタの選択の自由度が上がる分、コードは一般に複雑

Page 6: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

ISA of Parrot

Parrot

I (Integer)

N (Real)

S (String)

P (Polymorphic)

それぞれの型に応じてレジスタが用意されている

Ixx, Nxx, Sxx, Pxx

Page 7: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

ターゲット言語の重要な要素

スクリプト言語

動的型付け

文字列の操作

Arrayの操作

Page 8: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Parrot

Perl6用のVM

多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed

では、Parrotのうたい文句を見てみましょう

Parrot is a language-neutral virtual machine for dynamic

languages such as Ruby, Python, PHP, and Perl. It hosts a powerful suite of compiler tools tailored to dynamic languages and a next generation regular expression engine.

Page 9: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

少しambitiousなことが書いてある

Its architecture is fundamentally different than existing virtual machines such as the JVM or CLR, with optimizations for dynamic languages included, a register-based system rather than stack-based, and the use of continuations as the core means of flow control.

Page 10: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

構成

Parrot

VM

言語として

PIR 中間言語系

PASM アセンブリ言語

Page 11: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Parrotの構造

Parrot

Perl他ターゲット言語

PIR

PASM

PBC

PIR: Parrot Intermediate Language PASM: Parrot Assembly Language PBC: Parrot ByteCode

Page 12: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

では、Parrotの解析

データ型は

Integer

Number

String

PMC (PolyMorphic Container)

Page 13: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Register Machine

Registerとして

Ixx

Nxx

Sxx

Pxx

変数はスタックに積むことなく、「レジスタ名」でアクセスされる

Page 14: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

簡単な例(ただし分厚いライブラリ付)

.loadlib 'io_ops'

.pcc_sub :main main: getstdin P0 getstdout P1 REDO: readline S0, P0 print S0 if S0, REDO end

Page 15: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Parrotに求められるものは何か?

「オブジェクト」に対する動的な型付けのサポート。そのためにPMCを用意した

PMC

Scalar/array/subroutine/namespace を収容できる

目的に応じて柔軟に型変換が可能になっている

Page 16: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

PMCのタイプ

Env

Iterator

Array

Hash

String

Integer

Float

Exception

Timer

Page 17: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

たとえば、これはどうか(動的関係ない

.sub 'example' :main $I1 = 96 $I2 = 64 print "Algorithm E (Euclid's algorithm)¥n" e1: $I4 = mod $I1, $I2 e2: unless $I4 goto done e3: $I1 = $I2 $I2 = $I4 branch e1 done: print "The greatest common denominator of 96 and 64 is " print $I2 print ".¥n" .end

Page 18: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

ではこちらはどうか

$i = 4.3; print fact(); sub fact { $r = 1; while ($i > 0) { $r = $r * $i; $i--; } return $r; }

Page 19: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

解決方法

特定の演算を指定して、polymorphicにする

この場合はdecrement, multiply

PMCを引数に取る時の挙動を定める

→ VTABLEで処理内容を指定する

型指定のタイミングを変数の代入の時点で制御できるようにする

代入のsemanticsを定める

Page 20: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

実際 src/ops/math.opsでは

inline op dec(inout INT) { $1--; } inline op dec(inout NUM) { $1--; } inline op dec(invar PMC) { VTABLE_decrement(interp, $1); }

Page 21: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

ISA

まずは命令セットを眺めてみましょうか

src/include/oplib/ops.h

1129個の命令

高レベルのものを含む(特に制御関係)

Page 22: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

ISA 特に代入(set)を見てみましょう

inline op set(out INT, in INT) { $1 = $2; } inline op set(out INT, in NUM) { $1 = (INTVAL)($2); } inline op set(out INT, in STR) { $1 = Parrot_str_to_int(interp, $2); }

inline op set(out NUM, in NUM) { $1 = $2; } …

Page 23: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Non-trivialなsetは…

inline op set(invar PMC, in INT) { VTABLE_set_integer_native(interp, $1, $2); } inline op set(invar PMC, in NUM) { VTABLE_set_number_native(interp, $1, $2); } inline op set(invar PMC, invar STR) { VTABLE_set_string_native(interp, $1, $2); } inline op set(invar PMC, inconst STR) { VTABLE_set_string_native(interp, $1, $2); } inline op set(out INT, invar PMC) { $1 = VTABLE_get_integer(interp, $2); }

Page 24: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

Set

全体として以下のパターンに対してそれぞれ対応する関数が定められている

set (単純なパターン)

set P {I/N/S}

set Px [key] By/ set Ax Py[key]

白鳥は優雅に泳いでいるが…というパターン

Page 25: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

関数呼び出しについて(PIR)

まずはフレーム # factorial.pir .sub 'main' :main .local int count .local int product count = 5 product = 1 $I0 = 'fact'(count,

product) say $I0 .end

.sub 'fact' .param int c .param int p

loop: if c <= 1 goto fin p = c * p dec c branch loop fin: .return (p) .end

Page 26: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

PASMでの表現

.pcc_sub :main main:

new P10, 'ResizableIntegerArray'

set I1,0

## P9 is used as a stack for temporaries.

new P9, 'ResizableIntegerArray'

loop:

print "fact of "

print I1

print " is: "

new P0, 'Integer'

set P0,I1

local_branch P10, fact

print P0

print "¥n"

inc I1

eq I1,31,done

branch loop

done:

end

### P0 is the number to compute,and also the return value.

fact:

lt P0,2,is_one

## save I2, because we're gonna trash it.

push P9,I2

set I2,P0

dec P0

local_branch P10, fact

mul P0,P0,I2

pop I2,P9

local_return P10

is_one:

set P0,1

local_return P10

Page 27: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

まともなやつ

.pcc_sub :main main: # Get @ARGV as a

ResizableStringArray get_params "0", P0 # Discard the program

name shift S0, P0 # Look for additional args if P0, FOUND_EXTRA_ARG print "Hello World¥n" end

FOUND_EXTRA_ARG:

shift S1, P0

print "Hello "

print S1

print "¥n"

end

Page 28: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

関数コール

Signature で型付け

IN -> OUT

関数コールごとにcontextを作成(特別のスタックがあるわけではない)

Continuationを受け渡すことができる

Coroutine等が実現可能…

Page 29: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

OpCodeを見てみる

クラス関係

Callmethod, tailcallmethod, addmethod, can, does, isa (VTABLE), newclass, subclass, get_class, class, addparent, removeparent, addattribute, removeattribute, getattribute, setattribute, inspect

Page 30: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

文字列命令

ord, chr, chopn, concat, repeat, length, bytelength, pin, new, substr, replace, index, rindex, sprintf, upcase, downcase, titlecase, stringinfo, join, split, encoding, find_encoding, trans_encoding, finc_cclass, escape, compose, find_compose

Page 31: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

PMC

new, root_new, typeof, find_method, defined, exists, delete, elements, push, pop, shift, splice, setprop, getprop, freeze, thaw, box, iter,

Page 32: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

プロセス管理

Schedule, add_handler, wait, pass, invokecc, returncc, disable/enable-preemption, terminate,

関数コール

get/set_params, get/set_result

Page 33: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

名前解決

後は、グローバルな変数(名前でしかアクセスできないデータ)の扱いですが

以下の命令が用意されている

{store/find}_lex 名前付き変数の解決

get_namespace をやる前提で

get_global

set_global

find_name

Page 34: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

(問題9’’) ParrotについてJVMと同じことを解析せよ

Page 35: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

さてと、

レジスタ変数(またはスタック上の変数)の間の演算列という形でプログラムが書かれるようになれば「最適化」が可能になります

今までのtree traversalではできる最適化にも限度がありましたが…

「最適化」は性能をあげるためには必須です

Page 36: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

動的言語では

動的な型変換が性能にどれだけのマイナス要因になっているかを理解する

静的にでも動的にでも型変換のルーチンをスキップできれば、性能が上がる

JVM上でスクリプト言語を実行する場合

引数の動的型チェックを行う

引数の型チェックをできるものは静的にすませてしまう

Page 37: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

最適化の分類

1. ローカル最適化 1. 基本ブロック内外で、一定のパターンに当てはまるものを変換(ピープホール最適化)

2. 基本ブロック内で、変数の挙動を解析して変換

2. データフロー解析をもとにした大域最適化

3. データ依存解析をもとにしたループ最適化

4. 手続き間解析をもとにした手続き間最適化 1. LTO

2. WPRO

Page 38: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

動的型変換においては

ルーチン内で、型が伝播する可能性がある

ローカルな解析をもとにして

データフロー解析をもとにして

ルーチンをまたいで、型が分かる場合がある

手続き関解析をもとにして

Page 39: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

LTO (Link Time Optimization)

関数をまたいだ最適化を効率よく行うためにリンク時に最終的に最適化を行うことが普通になりつつある

コンパイラシステムがサポートすることも普通になってきている

Page 40: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

代表的な手続き間解析

部分評価

手続きに渡される引数の性質を利用する

int g(x) { if (x==0) return 1; else return h(x-1); } main() { print g(2)+g(0); }

Page 41: プログラミング言語処理系論 (9) · 2018. 10. 4. · Parrot Perl6用のVM 多くの動的型付け言語対応を唱う Rakudo Perl6 Lua Winxed では、Parrotのうたい文句を見てみましょう

では、これはどのくらい最適化の余地が…

.pcc_sub :main main:

new P10, 'ResizableIntegerArray'

set I1,0

## P9 is used as a stack for temporaries.

new P9, 'ResizableIntegerArray'

loop:

print "fact of "

print I1

print " is: "

new P0, 'Integer'

set P0,I1

local_branch P10, fact

print P0

print "¥n"

inc I1

eq I1,31,done

branch loop

done:

end

### P0 is the number to compute,and also the return value.

fact:

lt P0,2,is_one

## save I2, because we're gonna trash it.

push P9,I2

set I2,P0

dec P0

local_branch P10, fact

mul P0,P0,I2

pop I2,P9

local_return P10

is_one:

set P0,1

local_return P10