プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin:...
TRANSCRIPT
![Page 1: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/1.jpg)
プログラミング言語処理系論 (9) Design and Implementation of Programming Language Processors
佐藤周行
(情報基盤センター/電気系専攻融合情報学コース)
![Page 2: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/2.jpg)
今日の予定
Register machineの実際
Parrot
Stack machine vs Register machine
VMの設計
vmgen
![Page 3: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/3.jpg)
parrot.org/
![Page 4: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/4.jpg)
Register Machine
Register Machine
各種演算のオペランドにレジスタ(変数)を想定する
ハードウェア命令との親和性が高いと主張する
ハードウェアとの親和性を考えるとき、命令体系のレジスタセットとハードウェアのレジスタセットが異なる場合、「Register Allocation」が必要になる
レジスタの選択の自由度が上がる分、コードは一般に複雑
![Page 5: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/5.jpg)
ISA of Parrot
Parrot
I (Integer)
N (Real)
S (String)
P (Polymorphic)
それぞれの型に応じてレジスタが用意されている(実質無限個)
Ixx, Nxx, Sxx, Pxx
![Page 6: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/6.jpg)
ターゲット言語の重要な要素
スクリプト言語としてのPerlの特徴
動的型付け
実行時に文字列(S) か数(I, N)かが決まる
文字列の操作
パターン照合を含む
Arrayの操作
![Page 7: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/7.jpg)
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 8: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/8.jpg)
少し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 9: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/9.jpg)
構成
Parrot
VM
言語として
PIR 中間言語系
PASM アセンブリ言語
![Page 10: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/10.jpg)
Parrotの構造
Parrot
Perl他ターゲット言語
PIR
PASM
PBC
PIR: Parrot Intermediate Language PASM: Parrot Assembly Language PBC: Parrot ByteCode
![Page 11: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/11.jpg)
では、Parrotの解析
データ型は
Integer
Number
String
PMC (PolyMorphic Container)
![Page 12: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/12.jpg)
Register Machine
Registerとして
Ixx
Nxx
Sxx
Pxx
変数はスタックに積むことなく、「レジスタ名」でアクセスされる
![Page 13: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/13.jpg)
簡単な例(ただし分厚いライブラリ付)
.loadlib 'io_ops'
.pcc_sub :main main: getstdin P0 getstdout P1 REDO: readline S0, P0 print S0 if S0, REDO end
![Page 14: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/14.jpg)
Parrotに求められるものは何か?
「オブジェクト」に対する動的な型付けのサポート。そのためにPMCを用意した
PMC
Scalar/array/subroutine/namespace を収容できる
目的に応じて柔軟に型変換が可能になっている
![Page 15: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/15.jpg)
PMCのタイプ
Env
Iterator
Array
Hash
String
Integer
Float
Exception
Timer
![Page 16: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/16.jpg)
たとえば、これはどうか(動的関係ない
.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 17: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/17.jpg)
ではこちらはどうか
$i = 4.3; print fact(); sub fact { $r = 1; while ($i > 0) { $r = $r * $i; $i--; } return $r; }
![Page 18: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/18.jpg)
解決方法
特定の演算を指定して、polymorphicにする
この場合はdecrement, multiply
PMCを引数に取る時の挙動を定める
→ VTABLEで処理内容を指定する
型指定のタイミングを変数の代入の時点で制御できるようにする
代入のsemanticsを定める
![Page 19: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/19.jpg)
実際 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 20: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/20.jpg)
ISA
まずは命令セットを眺めてみましょうか
include/parrot/oplib/ops.h
1129個の命令
高レベルのものを含む(特に制御関係)
![Page 21: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/21.jpg)
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 22: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/22.jpg)
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 23: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/23.jpg)
Set
全体として以下のパターンに対してそれぞれ対応する関数が定められている
set (単純なパターン)
set P {I/N/S}
set Px [key] By/ set Ax Py[key]
白鳥は優雅に泳いでいるが…というパターン
![Page 24: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/24.jpg)
関数呼び出しについて(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 25: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/25.jpg)
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 26: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/26.jpg)
まともなやつ
.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 27: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/27.jpg)
関数コール
Signature で型付け
IN -> OUT
関数コールごとにcontextを作成(特別のスタックがあるわけではない)
Continuationを受け渡すことができる
Coroutine等が実現可能…
![Page 28: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/28.jpg)
OpCodeを見てみる
クラス関係
Callmethod, tailcallmethod, addmethod, can, does, isa (VTABLE), newclass, subclass, get_class, class, addparent, removeparent, addattribute, removeattribute, getattribute, setattribute, inspect
![Page 29: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/29.jpg)
文字列命令
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 30: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/30.jpg)
PMC
new, root_new, typeof, find_method, defined, exists, delete, elements, push, pop, shift, splice, setprop, getprop, freeze, thaw, box, iter,
![Page 31: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/31.jpg)
プロセス管理
schedule, add_handler, wait, pass, invokecc, returncc, disable/enable-preemption, terminate,
関数コール
get/set_params, get/set_result
![Page 32: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/32.jpg)
名前解決
後は、グローバルな変数(名前でしかアクセスできないデータ)の扱いですが
以下の命令が用意されている
{store/find}_lex 名前付き変数の解決
get_namespace をやる前提で
get_global
set_global
find_name
![Page 33: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/33.jpg)
(問題8’への追加) CPythonのVMについてJVMと同じことを解析せよ
(問題8’’) ParrotについてJVMと同じことを解析せよ
![Page 34: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/34.jpg)
stack machine vs. register machine
微妙なpros/consがある
少し古い論文だが
Y. Shi, K. Casey, M. A. Ertl, D. Gregg:
Virtual Machine Showdown: Stack Versus Registers, ACM Transactions on Architecture and Code Optimization, r(4), 2008.
(このグループはvmgenの開発者です)
![Page 35: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/35.jpg)
stack machineとregister machineはどちらが高速に動くか? JITコンパイラとは別の話
register machineを新たに定義し、JVMとの性能比較実験をしてみた vmgenを利用して気軽にVMが実装できる
生成されたコードは、load/storeに関して最適化を行った load/storeの挙動が両アーキテクチャの最大の違いであることはすぐわかる
![Page 36: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/36.jpg)
Load/Store
stack machine
(基本的に)演算の度にstackへのデータ移動が発生
対frame, 対constant pool, 対object pool
register machine
registerにデータを移動したら、registerを使って演算ができる
copy propagation, redundant load eliminationは性能を出すうえで必須の最適化
![Page 37: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/37.jpg)
性能比較
生成されたコードの比較 Naïveなstack register変換
Move 31%, constant load 28% (これがstack machineの特徴と考えてよい)
Load/storeの最適化後 命令数全体で44%削減 (ただし1命令あたりのサイズは大きくなっている コード量では26%削減)
Moveは大部分削除、constant loadは35%削減
実行されたコードの比較 Move 42% ほとんど削除 Constant loadは全体の6.4% 2.9% (実行頻度は少ない)
実行命令数全体で46%削減(NOT 実行時間)
![Page 38: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/38.jpg)
Load/Store
(VMではなく)実行プラットフォームCPUのload/store数の比較
VMでレジスタを実装しても、裏でメモリload/storeをする
register machineは、stack machineと比較してloadで35%削減、storeで48%削減
全体性能として、(dispatchに気を配れば)2倍程度性能向上(AMD64)
![Page 39: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/39.jpg)
オチとして
命令dispatchの方法の改善が重要
vmgenはいろいろ実験ができる。
switch文を使ったdispatch
ノーマルな方法
direct-threaded dispatch
Next PCの指す命令に対応するラベルに直接goto
言語のサポート必要(GCCならできる)
![Page 40: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/40.jpg)
Just in Time Compiler
昔、そういう技術がありまして… Javaの実行速度を上げるための工夫に使われた
実用的には、このアイデアはいろいろなところに残っている LTOなど
VM
CPU
Native code
VM code
実行直前にコンパイル
![Page 41: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/41.jpg)
Note
JVMの命令列をregister machineの命令列に変換したと言っているが…
Stack machineの命令列にする時点で情報がだいぶ落ちている
最適化の支障になる可能性がある(論文中で言及されている)
最適化をするなら、中間表現の設計に気を配るのが筋(これは次回以降のトピック)
![Page 42: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/42.jpg)
VMの設計
VMを設計する
Engine部分なら、ごく簡単
load/link、データ領域の確保を忘れずに
スレッド等、並列サポートもあればなおよい
![Page 43: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/43.jpg)
ターゲット言語の重要な要素
オブジェクト指向言語
オブジェクト
Method invocation
フレームは普通にスタックに積むのだが、Java VMではそこまでは強制されていない
スクリプト言語
動的型付け
文字列の操作が…
![Page 44: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/44.jpg)
決めるべきこと
ISA 重要なfeatureをサポートすることを考える
今まで説明してきたVMの真似から始めるのがよかろう
Minimum setとして何が必要かを考えると、言語の設計とリンクしてきます
データ、コードReference方法の決定 大昔はAddressing Modeなどと言いましてね…
Frame Management Call 関係の命令の実装
![Page 45: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/45.jpg)
VMの実装
Stack/register machine ISA
Code/data/stack segment
Symbol table
これらが決まったら、後は各命令の解釈を書くだけ
vmgenなど、便利そうに見えるツールがある
![Page 46: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/46.jpg)
問題10
Stack machineのVMを一つ設計せよ
命令セットはDCC.zip中のopcode.hを使うこと
stack segmentとdata segmentを定義すること
各命令を実行したときのstack/data segmentの状態変化を記述すること
OP_CALL とOP_RETURNについては詳述すること
この記述に従ってvmgenでVMを作成するとなおよい
コンパイラを作る必要はない
![Page 47: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/47.jpg)
VMGENの強調すること
VMGENは、Gforthの実装言語として世に出た(らしい)
http://savannah.gnu.org/projects/vmgen ここからダウンロードはできない。Project
HomepageにいってGforthをダウンロードするとついてくる
VMのエンジン部分を生成してくれる 命令dispatchに凝っている Switch (naïve, simple, but slow) Direct threaded dispatchのサポート
![Page 48: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/48.jpg)
Switch
vmexec(int pc)
{
for (;;) {
switch (codeseg[pc].op) {
case OP_NOP:
NEXTPC;
case OP_POP:
stacktop -= codeseg[pc].operand; NEXTPC;
case OP_U_NOT:
stackseg[stacktop] = !stackseg[stacktop]; NEXTPC;
case OP_B_ADD:
binop(+); NEXTPC;
case OP_B_SUB:
binop(-); NEXTPC;
![Page 49: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/49.jpg)
Direct Threaded Dispatch
vmexec(int pc)
{
for (;;) {
switch (codeseg[pc].op) {
case OP_NOP:
goto codeseg[NEXTPC];
case OP_POP:
stacktop -= codeseg[pc].operand;
goto codeseg[NEXTPC];
case OP_U_NOT:
stackseg[stacktop] = !stackseg[stacktop];
goto codeseg[NEXTPC]; case OP_B_ADD:
binop(+);
goto codeseg[NEXTPC];
case OP_B_SUB:
binop(-);
goto codeseg[NEXTPC];
![Page 50: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/50.jpg)
さてと、
レジスタ変数(またはスタック上の変数)の間の演算列という形でプログラムが書かれるようになれば「最適化」が可能になります
今までのtree traversalではできる最適化にも限度がありましたが…
「最適化」は性能をあげるためには必須です
register machine architectureでは、load/storeの最適化がstack machine architectureより劇的に効く– ことを説明しました
![Page 51: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/51.jpg)
動的言語では
動的な型変換が性能にどれだけのマイナス要因になっているかを理解する
静的にでも動的にでも型変換のルーチンをスキップできれば、性能が上がる
JVM上でスクリプト言語を実行する場合
引数の動的型チェックを行う
引数の型チェックをできるものは静的にすませてしまう
![Page 52: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/52.jpg)
動的型変換においては
ルーチン内で、型が伝播する可能性がある
ローカルな解析をもとにして
データフロー解析をもとにして
ルーチンをまたいで、型が分かる場合がある
手続き関解析をもとにして
![Page 53: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/53.jpg)
最適化の分類
1. ローカル最適化 1. 基本ブロック内外で、一定のパターンに当てはまるものを変換(ピープホール最適化)
2. 基本ブロック内で、変数の挙動を解析して変換
2. データフロー解析をもとにした大域最適化
3. データ依存解析をもとにしたループ最適化
4. 手続き間解析をもとにした手続き間最適化 1. LTO
2. WPRO
![Page 54: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/54.jpg)
LTO (Link Time Optimization)
関数をまたいだ最適化を効率よく行うためにリンク時に最終的に最適化を行うことが普通になりつつある
コンパイラシステムがサポートすることも普通になってきている
![Page 55: プログラミング言語処理系論 (9) - 東京大学...p = c * p dec c branch loop fin: .return (p) .end PASMでの表現 .pcc_sub :main main: compute,and also the return new](https://reader034.vdocuments.net/reader034/viewer/2022050103/5f42633270c5e52f1b7d007b/html5/thumbnails/55.jpg)
代表的な手続き間解析
部分評価
手続きに渡される引数の性質を利用する
int g(x) { if (x==0) return 1; else return h(x-1); } main() { print g(2)+g(0); }
int g(x) { if (x==0) return 1; else return h(x-1); } main() { print h(1)+1; }