12 分くらいで知るLuaVM

61
LuaVM 12 分くらいで知る LuaVM 2010224日水曜日

description

第三回カーネル/VM探検隊でLuaVMに関してLTをした資料です

Transcript of 12 分くらいで知るLuaVM

Page 1: 12 分くらいで知るLuaVM

LuaVM1 2 分 く ら い で 知 る L u a V M

2010年2月24日水曜日

Page 2: 12 分くらいで知るLuaVM

自己紹介

blog: 神様なんて信じない僕らのためにhatena: Isoparametrictwitter: isoparametric

name:イソッパ(http://d.hatena.ne.jp/Isoparametric/)

2010年2月24日水曜日

Page 3: 12 分くらいで知るLuaVM

Lua?

カーネルとか仮想化技術とは関係ありません。ごめんなさい、スクリプト言語です

Lua知らない人はググってください

一応説明しておくと、ブラジルで生まれた軽量で最速で最小で柔軟な組み込みに向いたLL言語です!(ANSI Cだけで記述)

2010年2月24日水曜日

Page 4: 12 分くらいで知るLuaVM

なんでLuaVM?単にプロジェクトでLuaを採用したから!

LuaとC系自作オリジナル言語(ただし、四則演算、if、forしかないプロトタイプ)を比較したらLuaの方が速かったから!

まぁ、Luaすげーなって思ったって、ことですよ

レジスタベースVMにも興味がありました

2010年2月24日水曜日

Page 5: 12 分くらいで知るLuaVM

今日の話

Luaのインストラクションセット

レジスタベースVMとスタックベースVM

その他

2010年2月24日水曜日

Page 6: 12 分くらいで知るLuaVM

海外の人曰くI think that one cannot completely grok a scripting language, or any complex system for that matter, without slitting the animal open and examining the entrails, organs and other yucky stuff that isn’t normally seen.

私は、動物を切り裂いて、内蔵、器官、その他不潔なものを調べずに、人がスクリプト言語、またはどんな複合システムをも完全に理解できるわけがないと思うの。

2010年2月24日水曜日

Page 7: 12 分くらいで知るLuaVM

LuaVMの素敵レジスタベースVM(5.0から)

中間コードによる最適化有り

Windowsでコンパイルして、組み込み機器で動作ということが簡単

パーサを切り離せるので、組み込みコードサイズが凄く小さい

2010年2月24日水曜日

Page 8: 12 分くらいで知るLuaVM

LuaVMの注意事項

内部構造は全く標準化されていないし、する気もない。ので、ユーザは内部構造に依存したコードを書いてはいけない。

故に、後にも先にも互換性を期待できない。

2010年2月24日水曜日

Page 9: 12 分くらいで知るLuaVM

VMのためのCPU用語集オペコード……CPU命令の番号のことオペランド……データが入っているメモリアドレス、あるいはジャンプ命令での飛び先、演算結果アドレス、ないしは定数データ部……プログラム内部で利用するデータが記録されている場所。命令にオペランドがある場合、ここまでジャンプして、データを取得/記録するPC……プログラムカウンタ。現在実行位置

釈迦に説法な

2010年2月24日水曜日

Page 10: 12 分くらいで知るLuaVM

VMのためのCPU用語集オペコード……CPU命令の番号のことオペランド……データが入っているメモリアドレス、あるいはジャンプ命令での飛び先、演算結果アドレス、ないしは定数データ部……プログラム内部で利用するデータが記録されている場所。命令にオペランドがある場合、ここまでジャンプして、データを取得/記録するPC……プログラムカウンタ。現在実行位置

釈迦に説法な

テストにでる!

2010年2月24日水曜日

Page 11: 12 分くらいで知るLuaVM

ザザッと見ようインストラクションセット38命令!(5.1.4時点)

R(X)はX番目のレジスタを意味

K(X)はX番目の定数を意味

RK(X)はR(X)か、K(X-k)を意味レジスタか定数と思って!(定数は負数で指すの)

/*----------------------------------------------------------------------name args description------------------------------------------------------------------------*/OP_MOVE,/* A B R(A) := R(B) */OP_LOADK,/* A Bx R(A) := Kst(Bx) */OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */OP_GETUPVAL,/* A B R(A) := UpValue[B] */OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */OP_SETUPVAL,/* A B UpValue[B] := R(A) */OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */OP_ADD,/* A B C R(A) := RK(B) + RK(C) */OP_SUB,/* A B C R(A) := RK(B) - RK(C) */OP_MUL,/* A B C R(A) := RK(B) * RK(C) */OP_DIV,/* A B C R(A) := RK(B) / RK(C) */OP_MOD,/* A B C R(A) := RK(B) % RK(C) */OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */OP_UNM,/* A B R(A) := -R(B) */OP_NOT,/* A B R(A) := not R(B) */OP_LEN,/* A B R(A) := length of R(B) */OP_CONCAT,/*A B C R(A) := R(B).. ... ..R(C) */OP_JMP,/* sBx pc+=sBx */OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */OP_RETURN,/*A B return R(A), ... ,R(A+B-2) (see note) */OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++*/ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */

2010年2月24日水曜日

Page 12: 12 分くらいで知るLuaVM

ザザッと見ようインストラクションセット38命令!(5.1.4時点)

R(X)はX番目のレジスタを意味

K(X)はX番目の定数を意味

RK(X)はR(X)か、K(X-k)を意味レジスタか定数と思って!(定数は負数で指すの)

/*----------------------------------------------------------------------name args description------------------------------------------------------------------------*/OP_MOVE,/* A B R(A) := R(B) */OP_LOADK,/* A Bx R(A) := Kst(Bx) */OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */OP_GETUPVAL,/* A B R(A) := UpValue[B] */OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */OP_SETUPVAL,/* A B UpValue[B] := R(A) */OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */OP_ADD,/* A B C R(A) := RK(B) + RK(C) */OP_SUB,/* A B C R(A) := RK(B) - RK(C) */OP_MUL,/* A B C R(A) := RK(B) * RK(C) */OP_DIV,/* A B C R(A) := RK(B) / RK(C) */OP_MOD,/* A B C R(A) := RK(B) % RK(C) */OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */OP_UNM,/* A B R(A) := -R(B) */OP_NOT,/* A B R(A) := not R(B) */OP_LEN,/* A B R(A) := length of R(B) */OP_CONCAT,/*A B C R(A) := R(B).. ... ..R(C) */OP_JMP,/* sBx pc+=sBx */OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */OP_RETURN,/*A B return R(A), ... ,R(A+B-2) (see note) */OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++*/ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */

2010年2月24日水曜日

Page 13: 12 分くらいで知るLuaVM

命令 用途

MOVE

LOADK

LOADBOOL

LOADNIL

GETUPVAL

GETGLOBAL

GETTABLE

SETGLOBAL

SETUPVAL

SETTABLE

レジスタ間の値コピー

定数をレジスタにロード

論理値をレジスタにロード

nilを指定範囲のレジスタにロード

上位値の値をレジスタにロード

グローバルの値をレジスタにロード

テーブル要素をレジスタにロード

レジスタの値をグローバルにセット

レジスタの値を上位値にセット

レジスタの値をテーブルにセット

2010年2月24日水曜日

Page 14: 12 分くらいで知るLuaVM

命令 用途

NEWTABLE

SELF

ADD

SUB

MUL

DIV

MOD

POW

UNM

NOT

新しいテーブルを生成

オブジェクトメソッドを呼ぶ準備

加算

減算

乗算

除算

剰余算

指数演算

単項マイナス

否定演算

2010年2月24日水曜日

Page 15: 12 分くらいで知るLuaVM

命令 用途

LEN

CONCAT

JMP

EQ

LT

LE

TEST

TESTSET

CALL

TAILCALL

長さ演算

レジスタ範囲内の要素を文字列連結

無条件ジャンプ

等価テスト&条件付きジャンプ

より小さいかテスト&条件付きジャンプ

以下テスト&条件付きジャンプ

論理値テスト&条件付きジャンプ

論理値テスト&条件付きジャンプ&代入

関数呼び出し

末尾関数呼び出し

2010年2月24日水曜日

Page 16: 12 分くらいで知るLuaVM

命令 用途

RETURN

FORLOOP

FORPREP

TFORLOOP

SETLIST

CLOSE

CLOSURE

VARARG

関数から戻る

数値forループ(FORPREPとセット)

数値forループ初期化

ジェネリックforループ

配列の要素をテーブルにセット

一部の上位値のローカル変数を閉じる

クロージャを生成

可変長引数をレジスタに割り当て

2010年2月24日水曜日

Page 17: 12 分くらいで知るLuaVM

インストラクションレイアウト0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

OP A B C

OP A Bx

OP A sBx

Figure 6: Instruction layout

function max (a,b)

local m = a 1 MOVE 2 0 0 ; R(2) = R(0)

if b > a then 2 LT 0 0 1 ; R(0) < R(1) ?

m = b 3 JMP 1 ; to 5 (4+1)

end 4 MOVE 2 1 0 ; R(2) = R(1)

return m 5 RETURN 2 2 0 ; return R(2)

end 6 RETURN 0 1 0 ; return

Figure 7: Bytecode for a Lua function

a register or a constant (using the representation RK(X) explained above). Withthis format, several typical operations in Lua can be coded in a single instruction.For instance, the increment of a local variable, such as a = a + 1, is codedas ADD x x y, where x represents the register holding the local variable and y

represents the constant 1. An assignment like a = b.f, when both a and b arelocal variables, is also coded as the single instruction GETTABLE x y z, where x

is the register for a, y is the register for b, and z is the index of the stringconstant "f". (In Lua, the syntax b.f is syntactic sugar for b["f"], that is, bindexed by the string "f".)

Branch instructions pose a di!culty because they need to specify two operandsto be compared plus a jump o"set. Packing all this data inside a single instruc-tion would limit jump o"sets to 256 (assuming a signed 9-bit field). The solutionadopted in Lua is that, conceptually, a test instruction simply skips the next in-struction when the test fails; this next instruction is a regular jump, which usesan 18-bit o"set. Actually, because a test instruction is always followed by a jumpinstruction, the interpreter executes both instructions together. That is, whenexecuting a test instruction that succeeds, the interpreter immediately fetchesthe next instruction and does the jump, instead of doing it in the next dispatchcycle. Figure 7 shows an example of Lua code and the corresponding bytecode.Note the structure of the conditional and jump instructions just described.

Figure 8 shows a small sample of the optimizations performed by the Luacompiler. Figure 9 shows the same code compiled for Lua 4.0, which used a stack-

OPコードは6bit

その他はオペランドです。フィールドAは常にあって8bit

フィールドのBとCは9bitですが、18bitとしても使われます。Bx(unsigned) or sBx(signed)

2010年2月24日水曜日

Page 18: 12 分くらいで知るLuaVM

関数で追ってみる

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

OP A B C

OP A Bx

OP A sBx

Figure 6: Instruction layout

function max (a,b)

local m = a 1 MOVE 2 0 0 ; R(2) = R(0)

if b > a then 2 LT 0 0 1 ; R(0) < R(1) ?

m = b 3 JMP 1 ; to 5 (4+1)

end 4 MOVE 2 1 0 ; R(2) = R(1)

return m 5 RETURN 2 2 0 ; return R(2)

end 6 RETURN 0 1 0 ; return

Figure 7: Bytecode for a Lua function

a register or a constant (using the representation RK(X) explained above). Withthis format, several typical operations in Lua can be coded in a single instruction.For instance, the increment of a local variable, such as a = a + 1, is codedas ADD x x y, where x represents the register holding the local variable and y

represents the constant 1. An assignment like a = b.f, when both a and b arelocal variables, is also coded as the single instruction GETTABLE x y z, where x

is the register for a, y is the register for b, and z is the index of the stringconstant "f". (In Lua, the syntax b.f is syntactic sugar for b["f"], that is, bindexed by the string "f".)

Branch instructions pose a di!culty because they need to specify two operandsto be compared plus a jump o"set. Packing all this data inside a single instruc-tion would limit jump o"sets to 256 (assuming a signed 9-bit field). The solutionadopted in Lua is that, conceptually, a test instruction simply skips the next in-struction when the test fails; this next instruction is a regular jump, which usesan 18-bit o"set. Actually, because a test instruction is always followed by a jumpinstruction, the interpreter executes both instructions together. That is, whenexecuting a test instruction that succeeds, the interpreter immediately fetchesthe next instruction and does the jump, instead of doing it in the next dispatchcycle. Figure 7 shows an example of Lua code and the corresponding bytecode.Note the structure of the conditional and jump instructions just described.

Figure 8 shows a small sample of the optimizations performed by the Luacompiler. Figure 9 shows the same code compiled for Lua 4.0, which used a stack-

2010年2月24日水曜日

Page 19: 12 分くらいで知るLuaVM

関数で追ってみる

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

OP A B C

OP A Bx

OP A sBx

Figure 6: Instruction layout

function max (a,b)

local m = a 1 MOVE 2 0 0 ; R(2) = R(0)

if b > a then 2 LT 0 0 1 ; R(0) < R(1) ?

m = b 3 JMP 1 ; to 5 (4+1)

end 4 MOVE 2 1 0 ; R(2) = R(1)

return m 5 RETURN 2 2 0 ; return R(2)

end 6 RETURN 0 1 0 ; return

Figure 7: Bytecode for a Lua function

a register or a constant (using the representation RK(X) explained above). Withthis format, several typical operations in Lua can be coded in a single instruction.For instance, the increment of a local variable, such as a = a + 1, is codedas ADD x x y, where x represents the register holding the local variable and y

represents the constant 1. An assignment like a = b.f, when both a and b arelocal variables, is also coded as the single instruction GETTABLE x y z, where x

is the register for a, y is the register for b, and z is the index of the stringconstant "f". (In Lua, the syntax b.f is syntactic sugar for b["f"], that is, bindexed by the string "f".)

Branch instructions pose a di!culty because they need to specify two operandsto be compared plus a jump o"set. Packing all this data inside a single instruc-tion would limit jump o"sets to 256 (assuming a signed 9-bit field). The solutionadopted in Lua is that, conceptually, a test instruction simply skips the next in-struction when the test fails; this next instruction is a regular jump, which usesan 18-bit o"set. Actually, because a test instruction is always followed by a jumpinstruction, the interpreter executes both instructions together. That is, whenexecuting a test instruction that succeeds, the interpreter immediately fetchesthe next instruction and does the jump, instead of doing it in the next dispatchcycle. Figure 7 shows an example of Lua code and the corresponding bytecode.Note the structure of the conditional and jump instructions just described.

Figure 8 shows a small sample of the optimizations performed by the Luacompiler. Figure 9 shows the same code compiled for Lua 4.0, which used a stack-

引数はローカル変数なので、レジスタにマッピングされる。この場合なら、R(0) == a, R(1) == b

LTは条件が成立なら次がジャンプ命令なのでジャンプ不成立ならPC++なので、直後のJMP命令を飛ばす

OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */2010年2月24日水曜日

Page 20: 12 分くらいで知るLuaVM

小粋な分岐比較時に2つのオペランドを指定すると、分岐命令はちょっと困難になります。

1つの命令で全データを保持しようとすると、ジャンプオフセットは256に制限されてしまうので(B/Cの9bit==1bitは符号)

Luaはテストが成功したら、次にジャンプ命令を置くようにしました。これなら、18bitのオフセットが使えます(131071まで)

2010年2月24日水曜日

Page 21: 12 分くらいで知るLuaVM

という人も、VMが分からなくてもLuaは使えるので

気にしないでね!VMが気になってきたら、

ソースコードを書いてlua -lで出力できるよ2010年2月24日水曜日

Page 22: 12 分くらいで知るLuaVM

Luaの歴史1.0 1.1 2.1 2.2 2.4 2.5 3.0 3.1 3.2 4.0 5.0 5.1

constructors • • • • • • • • • • • •garbage collection • • • • • • • • • • • •extensible semantics ◦ ◦ • • • • • • • • • •support for OOP ◦ ◦ • • • • • • • • • •long strings ◦ ◦ ◦ • • • • • • • • •debug API ◦ ◦ ◦ • • • • • • • • •external compiler ◦ ◦ ◦ ◦ • • • • • • • •vararg functions ◦ ◦ ◦ ◦ ◦ • • • • • • •pattern matching ◦ ◦ ◦ ◦ ◦ • • • • • • •conditional compilation ◦ ◦ ◦ ◦ ◦ ◦ • • • ◦ ◦ ◦anonymous functions, closures ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • • • •debug library ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • • •multi-state API ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • •for statement ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • •long comments ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •full lexical scoping ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •booleans ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •coroutines ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •incremental garbage collection ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ •module system ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ •

1.0 1.1 2.1 2.2 2.4 2.5 3.0 3.1 3.2 4.0 5.0 5.1libraries 4 4 4 4 4 4 4 4 5 6 8 9built-in functions 5 7 11 11 13 14 25 27 35 0 0 0API functions 30 30 30 30 32 32 33 47 41 60 76 79vm type (stack × register) S S S S S S S S S S R Rvm instructions 64 65 69 67 67 68 69 128 64 49 35 38keywords 16 16 16 16 16 16 16 16 16 18 21 21other tokens 21 21 23 23 23 23 24 25 25 25 24 26

Table 1. The evolution of features in Lua.

Lua was becoming a mature product and needed stability forthe benefit of its growing community. Nevertheless, the needfor stability has not hindered progress. Major new versionsof Lua, such as Lua 4.0 and Lua 5.0, have been released sincethen.

The long times between versions also reflects our releasemodel. Unlike other open-source projects, our alpha versionsare quite stable and beta versions are essentially final, exceptfor uncovered bugs.2 This release model has proved to begood for Lua stability. Several products have been shippedwith alpha or beta versions of Lua and worked fine. How-ever, this release model did not give users much chance toexperiment with new versions; it also deprived us of timelyfeedback on proposed changes. So, during the developmentof Lua 5.0 we started to release “work” versions, which arejust snapshots of the current development of Lua. This movebrought our current release model closer to the “ReleaseEarly, Release Often” motto of the open-source community.

2 The number of bugs found after final versions were released has beenconsistently small: only 10 in Lua 4.0, 17 in Lua 5.0, and 10 in Lua 5.1so far, none of them critical bugs.

In the remainder of this section we discuss some mile-stones in the evolution of Lua. Details on the evolution ofseveral specific features are given in §6. Table 1 summarizesthis evolution. It also contains statistics about the size of Lua,which we now discuss briefly.

The number of standard libraries has been kept small be-cause we expect that most Lua functions will be provided bythe host application or by third-party libraries. Until Lua 3.1,the only standard libraries were for input and output, stringmanipulation, mathematical functions, and a special libraryof built-in functions, which did not use the C API but directlyaccessed the internal data structures. Since then, we haveadded libraries for debugging (Lua 3.2), interfacing with theoperating system (Lua 4.0), tables and coroutines (Lua 5.0),and modules (Lua 5.1).

The size of C API changed significantly when it was re-designed in Lua 4.0. Since then, it has moved slowly towardcompleteness. As a consequence, there are no longer anybuilt-in functions: all standard libraries are implemented ontop the C API, without accessing the internals of Lua.

The virtual machine, which executes Lua programs, wasstack-based until Lua 4.0. In Lua 3.1 we added variants

2010年2月24日水曜日

Page 23: 12 分くらいで知るLuaVM

Luaの歴史1.0 1.1 2.1 2.2 2.4 2.5 3.0 3.1 3.2 4.0 5.0 5.1

constructors • • • • • • • • • • • •garbage collection • • • • • • • • • • • •extensible semantics ◦ ◦ • • • • • • • • • •support for OOP ◦ ◦ • • • • • • • • • •long strings ◦ ◦ ◦ • • • • • • • • •debug API ◦ ◦ ◦ • • • • • • • • •external compiler ◦ ◦ ◦ ◦ • • • • • • • •vararg functions ◦ ◦ ◦ ◦ ◦ • • • • • • •pattern matching ◦ ◦ ◦ ◦ ◦ • • • • • • •conditional compilation ◦ ◦ ◦ ◦ ◦ ◦ • • • ◦ ◦ ◦anonymous functions, closures ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • • • •debug library ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • • •multi-state API ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • •for statement ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • •long comments ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •full lexical scoping ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •booleans ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •coroutines ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •incremental garbage collection ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ •module system ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ •

1.0 1.1 2.1 2.2 2.4 2.5 3.0 3.1 3.2 4.0 5.0 5.1libraries 4 4 4 4 4 4 4 4 5 6 8 9built-in functions 5 7 11 11 13 14 25 27 35 0 0 0API functions 30 30 30 30 32 32 33 47 41 60 76 79vm type (stack × register) S S S S S S S S S S R Rvm instructions 64 65 69 67 67 68 69 128 64 49 35 38keywords 16 16 16 16 16 16 16 16 16 18 21 21other tokens 21 21 23 23 23 23 24 25 25 25 24 26

Table 1. The evolution of features in Lua.

Lua was becoming a mature product and needed stability forthe benefit of its growing community. Nevertheless, the needfor stability has not hindered progress. Major new versionsof Lua, such as Lua 4.0 and Lua 5.0, have been released sincethen.

The long times between versions also reflects our releasemodel. Unlike other open-source projects, our alpha versionsare quite stable and beta versions are essentially final, exceptfor uncovered bugs.2 This release model has proved to begood for Lua stability. Several products have been shippedwith alpha or beta versions of Lua and worked fine. How-ever, this release model did not give users much chance toexperiment with new versions; it also deprived us of timelyfeedback on proposed changes. So, during the developmentof Lua 5.0 we started to release “work” versions, which arejust snapshots of the current development of Lua. This movebrought our current release model closer to the “ReleaseEarly, Release Often” motto of the open-source community.

2 The number of bugs found after final versions were released has beenconsistently small: only 10 in Lua 4.0, 17 in Lua 5.0, and 10 in Lua 5.1so far, none of them critical bugs.

In the remainder of this section we discuss some mile-stones in the evolution of Lua. Details on the evolution ofseveral specific features are given in §6. Table 1 summarizesthis evolution. It also contains statistics about the size of Lua,which we now discuss briefly.

The number of standard libraries has been kept small be-cause we expect that most Lua functions will be provided bythe host application or by third-party libraries. Until Lua 3.1,the only standard libraries were for input and output, stringmanipulation, mathematical functions, and a special libraryof built-in functions, which did not use the C API but directlyaccessed the internal data structures. Since then, we haveadded libraries for debugging (Lua 3.2), interfacing with theoperating system (Lua 4.0), tables and coroutines (Lua 5.0),and modules (Lua 5.1).

The size of C API changed significantly when it was re-designed in Lua 4.0. Since then, it has moved slowly towardcompleteness. As a consequence, there are no longer anybuilt-in functions: all standard libraries are implemented ontop the C API, without accessing the internals of Lua.

The virtual machine, which executes Lua programs, wasstack-based until Lua 4.0. In Lua 3.1 we added variants

条件付きコンパイル消滅

2010年2月24日水曜日

Page 24: 12 分くらいで知るLuaVM

Luaの歴史1.0 1.1 2.1 2.2 2.4 2.5 3.0 3.1 3.2 4.0 5.0 5.1

constructors • • • • • • • • • • • •garbage collection • • • • • • • • • • • •extensible semantics ◦ ◦ • • • • • • • • • •support for OOP ◦ ◦ • • • • • • • • • •long strings ◦ ◦ ◦ • • • • • • • • •debug API ◦ ◦ ◦ • • • • • • • • •external compiler ◦ ◦ ◦ ◦ • • • • • • • •vararg functions ◦ ◦ ◦ ◦ ◦ • • • • • • •pattern matching ◦ ◦ ◦ ◦ ◦ • • • • • • •conditional compilation ◦ ◦ ◦ ◦ ◦ ◦ • • • ◦ ◦ ◦anonymous functions, closures ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • • • •debug library ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • • •multi-state API ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • •for statement ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • • •long comments ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •full lexical scoping ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •booleans ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •coroutines ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ • •incremental garbage collection ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ •module system ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ •

1.0 1.1 2.1 2.2 2.4 2.5 3.0 3.1 3.2 4.0 5.0 5.1libraries 4 4 4 4 4 4 4 4 5 6 8 9built-in functions 5 7 11 11 13 14 25 27 35 0 0 0API functions 30 30 30 30 32 32 33 47 41 60 76 79vm type (stack × register) S S S S S S S S S S R Rvm instructions 64 65 69 67 67 68 69 128 64 49 35 38keywords 16 16 16 16 16 16 16 16 16 18 21 21other tokens 21 21 23 23 23 23 24 25 25 25 24 26

Table 1. The evolution of features in Lua.

Lua was becoming a mature product and needed stability forthe benefit of its growing community. Nevertheless, the needfor stability has not hindered progress. Major new versionsof Lua, such as Lua 4.0 and Lua 5.0, have been released sincethen.

The long times between versions also reflects our releasemodel. Unlike other open-source projects, our alpha versionsare quite stable and beta versions are essentially final, exceptfor uncovered bugs.2 This release model has proved to begood for Lua stability. Several products have been shippedwith alpha or beta versions of Lua and worked fine. How-ever, this release model did not give users much chance toexperiment with new versions; it also deprived us of timelyfeedback on proposed changes. So, during the developmentof Lua 5.0 we started to release “work” versions, which arejust snapshots of the current development of Lua. This movebrought our current release model closer to the “ReleaseEarly, Release Often” motto of the open-source community.

2 The number of bugs found after final versions were released has beenconsistently small: only 10 in Lua 4.0, 17 in Lua 5.0, and 10 in Lua 5.1so far, none of them critical bugs.

In the remainder of this section we discuss some mile-stones in the evolution of Lua. Details on the evolution ofseveral specific features are given in §6. Table 1 summarizesthis evolution. It also contains statistics about the size of Lua,which we now discuss briefly.

The number of standard libraries has been kept small be-cause we expect that most Lua functions will be provided bythe host application or by third-party libraries. Until Lua 3.1,the only standard libraries were for input and output, stringmanipulation, mathematical functions, and a special libraryof built-in functions, which did not use the C API but directlyaccessed the internal data structures. Since then, we haveadded libraries for debugging (Lua 3.2), interfacing with theoperating system (Lua 4.0), tables and coroutines (Lua 5.0),and modules (Lua 5.1).

The size of C API changed significantly when it was re-designed in Lua 4.0. Since then, it has moved slowly towardcompleteness. As a consequence, there are no longer anybuilt-in functions: all standard libraries are implemented ontop the C API, without accessing the internals of Lua.

The virtual machine, which executes Lua programs, wasstack-based until Lua 4.0. In Lua 3.1 we added variants

条件付きコンパイル消滅

命令数を増やして効率化終了

2010年2月24日水曜日

Page 25: 12 分くらいで知るLuaVM

レジスタベースVMV S ス タ ッ ク ベ ー ス V M

2010年2月24日水曜日

Page 26: 12 分くらいで知るLuaVM

スタックベースVM?スタックベースVMは計算要素などをスタックにpushしてから計算命令を実行するようにオペコードが設計されている

構造がシンプルで、移植性が高く、暗黙にスタックに対する操作であると決定づけができるので命令サイズが小さくできる

古典的VMは殆どスタックベースVM

2010年2月24日水曜日

Page 27: 12 分くらいで知るLuaVM

レジスタベースVM?Luaの人曰く広く使われたレジスタベースVMはLuaが初めてのもの局所変数をレジスタに割り付けるので効率的だよ(引数やlocal変数など)オペランドを使って命令総数を減らせるよスタックにコピーするコストがないよ(push/popのコストがないよ)

2010年2月24日水曜日

Page 28: 12 分くらいで知るLuaVM

LuaVMの性質Luaのレジスタはランタイムのスタックに配置されます(それは単なる配列です)。なので速い!(と言ってます)

ローカルでないグローバル変数なども、ただのテーブルなので、変数名に対応したハッシュ値は事前計算されているので速いよ!

2010年2月24日水曜日

Page 29: 12 分くらいで知るLuaVM

あれ?ランタイムスタック==レジスタ==スタックじゃね?

2010年2月24日水曜日

Page 30: 12 分くらいで知るLuaVM

あれ?ランタイムスタック==レジスタ==スタックじゃね?

嘘じゃないんだよー、そういうVMなんだよー

LuaがレジスタベースVMとか……

2010年2月24日水曜日

Page 31: 12 分くらいで知るLuaVM

メリットだけではない

レジスタマシンの問題は2つある

1つは命令サイズの問題

もう1つデコードのオーバヘッド

2010年2月24日水曜日

Page 32: 12 分くらいで知るLuaVM

命令サイズの問題レジスタマシンでは、オペランドの指定があるので、スタックマシンよりオペコードが大きくなります(LuaVMのオペコードサイズは4byte。対して、以前のLuaなら1byteか2byteだった)

しかし、オペコードの量が少なくなるので、総コードサイズはそこまで大きくならないですよ、と言ってます

2010年2月24日水曜日

Page 33: 12 分くらいで知るLuaVM

デコードの問題スタックマシンのオペコードには、暗黙の指示があるので単純で速い。例えばADD

(ADDはスタックにのっている2つの数を加算するだけなのでADDだけで済む)

レジスタマシンはオペランド解析があるので、オーバヘッドが加算されてしまう(ADDならどのレジスタ同志の加算かのオペランド情報+解析が必要)

2010年2月24日水曜日

Page 34: 12 分くらいで知るLuaVM

が、スタックマシンもどうせスタック操作が入るし、オペランド解析の方が論理演算などで済むので実際にはコストは安い

しかも、スタックマシンはよくマルチバイトオペランド(JavaVMなら分岐やgotoの2byte)を必要にするので、移植性含めてアライメントの問題などを考えたとき、オペランドをとってくるコストはレジスタマシンの方が安い(マシンによっては2byte単位でとれないかもだし)

2010年2月24日水曜日

Page 35: 12 分くらいで知るLuaVM

レジスタマシン スタックマシン

オペコードサイズ

オペコード量

実行時オペランド解析

レジスタに対する操作なので大きくなる

Luaなら4byte

スタックに対する操作なので小さくて済む

Luaなら1 or 2byte

少なくて済む半分から三分の一

スタック操作の都合上多くなる

する しない

2010年2月24日水曜日

Page 36: 12 分くらいで知るLuaVM

local a,t,ia=a+ia=a+100a=t[i]

これをオペコードにすると!(ちなみにこの例は実行時エラーになるYO)

2010年2月24日水曜日

Page 37: 12 分くらいで知るLuaVM

1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

local a,t,ia=a+ia=a+100a=t[i]

スタックベース

これをオペコードにすると!(ちなみにこの例は実行時エラーになるYO)

2010年2月24日水曜日

Page 38: 12 分くらいで知るLuaVM

1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

1 [2]ADD 0 0 22 [3]ADD 0 0 -1 ; - 1003 [4]GETTABLE 0 1 24 [4]RETURN 0 1

local a,t,ia=a+ia=a+100a=t[i]

スタックベース レジスタベース

これをオペコードにすると!(ちなみにこの例は実行時エラーになるYO)

2010年2月24日水曜日

Page 39: 12 分くらいで知るLuaVM

Lua 4.0.1(スタックベース)の場合

main <0:@test.lua> (12 instructions/96 bytes at 0x100100650)0 params, 5 stacks, 3 locals, 0 strings, 0 numbers, 0 functions, 5 lines 1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

2010年2月24日水曜日

Page 40: 12 分くらいで知るLuaVM

Lua 4.0.1(スタックベース)の場合

main <0:@test.lua> (12 instructions/96 bytes at 0x100100650)0 params, 5 stacks, 3 locals, 0 strings, 0 numbers, 0 functions, 5 lines 1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

local a,t,i

2010年2月24日水曜日

Page 41: 12 分くらいで知るLuaVM

Lua 4.0.1(スタックベース)の場合

main <0:@test.lua> (12 instructions/96 bytes at 0x100100650)0 params, 5 stacks, 3 locals, 0 strings, 0 numbers, 0 functions, 5 lines 1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

local a,t,i

a=a+i

2010年2月24日水曜日

Page 42: 12 分くらいで知るLuaVM

Lua 4.0.1(スタックベース)の場合

main <0:@test.lua> (12 instructions/96 bytes at 0x100100650)0 params, 5 stacks, 3 locals, 0 strings, 0 numbers, 0 functions, 5 lines 1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

local a,t,i

a=a+i

a=a+100

2010年2月24日水曜日

Page 43: 12 分くらいで知るLuaVM

Lua 4.0.1(スタックベース)の場合

main <0:@test.lua> (12 instructions/96 bytes at 0x100100650)0 params, 5 stacks, 3 locals, 0 strings, 0 numbers, 0 functions, 5 lines 1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

local a,t,i

a=a+i

a=a+100

a=t[i]

2010年2月24日水曜日

Page 44: 12 分くらいで知るLuaVM

Lua 4.0.1(スタックベース)の場合

main <0:@test.lua> (12 instructions/96 bytes at 0x100100650)0 params, 5 stacks, 3 locals, 0 strings, 0 numbers, 0 functions, 5 lines 1[1]PUSHNIL 3 2[2]GETLOCAL 0 ; a 3[2]GETLOCAL 2 ; i 4[2]ADD 5[2]SETLOCAL 0 ; a 6[3]GETLOCAL 0 ; a 7[3]ADDI 100 8[3]SETLOCAL 0 ; a 9[4]GETLOCAL 1 ; t 10[4]GETINDEXED 2 ; i 11[4]SETLOCAL 0 ; a 12[4]END

local a,t,i

a=a+i

a=a+100

a=t[i]

殆どスタックに対する操作じゃないかYO!

ADDとか、ADDIはスタックにある要素に対する操作なので仕方がない……

2010年2月24日水曜日

Page 45: 12 分くらいで知るLuaVM

main <test.lua:0,0> (4 instructions, 16 bytes at 0x100101050)0+ params, 3 slots, 0 upvalues, 3 locals, 1 constant, 0 functions 1 [2] ADD 0 0 2 2 [3] ADD 0 0 -1 ; - 100 3 [4] GETTABLE 0 1 2 4 [4] RETURN 0 1

Lua 5.1.4(レジスタベース)の場合

2010年2月24日水曜日

Page 46: 12 分くらいで知るLuaVM

main <test.lua:0,0> (4 instructions, 16 bytes at 0x100101050)0+ params, 3 slots, 0 upvalues, 3 locals, 1 constant, 0 functions 1 [2] ADD 0 0 2 2 [3] ADD 0 0 -1 ; - 100 3 [4] GETTABLE 0 1 2 4 [4] RETURN 0 1

Lua 5.1.4(レジスタベース)の場合

a=a+i

2010年2月24日水曜日

Page 47: 12 分くらいで知るLuaVM

main <test.lua:0,0> (4 instructions, 16 bytes at 0x100101050)0+ params, 3 slots, 0 upvalues, 3 locals, 1 constant, 0 functions 1 [2] ADD 0 0 2 2 [3] ADD 0 0 -1 ; - 100 3 [4] GETTABLE 0 1 2 4 [4] RETURN 0 1

Lua 5.1.4(レジスタベース)の場合

a=a+ia=a+100

2010年2月24日水曜日

Page 48: 12 分くらいで知るLuaVM

main <test.lua:0,0> (4 instructions, 16 bytes at 0x100101050)0+ params, 3 slots, 0 upvalues, 3 locals, 1 constant, 0 functions 1 [2] ADD 0 0 2 2 [3] ADD 0 0 -1 ; - 100 3 [4] GETTABLE 0 1 2 4 [4] RETURN 0 1

Lua 5.1.4(レジスタベース)の場合

a=a+ia=a+100a=t[i]

2010年2月24日水曜日

Page 49: 12 分くらいで知るLuaVM

main <test.lua:0,0> (4 instructions, 16 bytes at 0x100101050)0+ params, 3 slots, 0 upvalues, 3 locals, 1 constant, 0 functions 1 [2] ADD 0 0 2 2 [3] ADD 0 0 -1 ; - 100 3 [4] GETTABLE 0 1 2 4 [4] RETURN 0 1

Lua 5.1.4(レジスタベース)の場合

a=a+ia=a+100a=t[i]

パラメータは多いけど、わかりやすい状態になった。

そして、結果的に省メモリになってる。local a,t,iも命令として消えてるし……。

2010年2月24日水曜日

Page 50: 12 分くらいで知るLuaVM

というわけでもないのかなーとは思います2010年2月24日水曜日

Page 51: 12 分くらいで知るLuaVM

なぜか?本気でやるとレジスタ割り当てのためコード生成の実装が複雑になるので難しくなる(Luaは微塵もやってない:-p)

レジスタはハードウェアレジスタではないので、そこまで速くならない

関数呼び出しなどには結局スタックを使う羽目になる

頑張った割に報われない、らしい……

2010年2月24日水曜日

Page 52: 12 分くらいで知るLuaVM

それでもLuaでレジスタベースが有効な理由

Luaでは、数値でも12byte(tag+実体のunion)で、スタックへのコピーコストが高いのでなくしたかった

固定長の命令セットにできるのでアライメントの問題で効率がこれだけでも良くなる

普通の努力でそこそこの結果がでてる

2010年2月24日水曜日

Page 53: 12 分くらいで知るLuaVM

こんなに速くなりました

8 Conclusion

In this paper we have presented the most innovative aspects of the implementa-tion of Lua 5.0: its register-based virtual machine, the new algorithm for opti-mizing tables used as arrays, and the implementation of closures.

To our knowledge, Lua is the first language in wide use to adopt a register-based virtual machine. The optimization for tables allows a table to be partiallyimplemented as an array when it is used that way (that is, when it has enoughkeys in a range 1 . . . n). Its implementation of closures is also unique, combin-ing the use of an array-based stack with lexically scoped first-order functions,without complex control-flow analysis.

The table in Figure 10 shows some simple performance comparisons betweenthe old implementation and the new one. The tests were run on an Intel Pen-tium IV machine with 512 Mbytes running Linux 2.6, with Lua compiled withgcc 3.3. Lua 4.0 uses neither the register-based virtual machine (its machine isstack based) nor the table–array optimization. Lua 5’ is Lua 5.0 without table–array optimization, tail calls, and dynamic stacks (related to coroutines); Lua 5’is essentially Lua 4.0 with the new register-based virtual machine.

We took all test cases from The Great Computer Language Shootout [2],except the first one (sum), which is a simple loop to add all integers from 1to n. This first test spends most of its time in the virtual machine; it shows thatthe new virtual machine can be more than twice as fast as the old one. The othertests spend more time in other tasks (function calls, table/array access, etc.),so the gain in the virtual machine has a smaller e!ect on the total time. In thetests that use arrays (sieve, heapsort, and matrix ), the combination of the newvirtual machine with the new optimization for arrays can reduce the runningtime up to 40%.

The complete code of Lua 5.0 is available for browsing at Lua’s web site:http://www.lua.org/source/5.0/.

program Lua 4.0 Lua 5’ Lua 5.0

sum (2e7) 1.23 0.54 (44%) 0.54 (44%)

fibo (30) 0.95 0.68 (72%) 0.69 (73%)

ack (8) 1.00 0.86 (86%) 0.88 (88%)

random (1e6) 1.04 0.96 (92%) 0.96 (92%)

sieve (100) 0.93 0.82 (88%) 0.57 (61%)

heapsort (5e4) 1.08 1.05 (97%) 0.70 (65%)

matrix (50) 0.84 0.82 (98%) 0.59 (70%)

Figure 10: Benchmarks (times in seconds; percentages are relative to Lua 4.0)Luaのレジスタマシンが一般のレジスタマシンではないので参考までに

2010年2月24日水曜日

Page 54: 12 分くらいで知るLuaVM

その他関 数 コ ー ル と 他 言 語 L u a V M

2010年2月24日水曜日

Page 55: 12 分くらいで知るLuaVM

Luaの関数コールLuaは関数コールに2つのスタックを使います1つは戻りアドレスなどを保持するものもう1つは、単にLua変数の配列です(引数、local変数の一時変数保持)一般的に「リターンスタック」と「データスタック」と呼ぶものレジスタ・ウィンドウも使ってるよ

2010年2月24日水曜日

Page 56: 12 分くらいで知るLuaVM

レジスタ・ウィンドウプログラムの各部分ごとにレジスタセットを提供する技法

レジスタが簡単に溢れないようにプロシージャコールごとに見えるレジスタを制限する

Luaでは単に仮想レジスタをその都度作る

2010年2月24日水曜日

Page 57: 12 分くらいで知るLuaVM

他環境でのLuaVMLua-Alchemy(Lua on Flash)

kahlua(Lua on Java[J2ME])

Yueliang(Lua on Lua)

LuaCLR(Lua on .NET)

Lua2js(Lua on JavaScript)

詳しくはhttp://lua-users.org/wiki/

LuaImplementations

2010年2月24日水曜日

Page 59: 12 分くらいで知るLuaVM

まとめLuaのインストラクションセットはシンプルだよ!

古典的なスタックベースも良いけど、レジスタベースも良いよ!

Luaはレジスタベースで頑張ったので偉い!(レジスタ割り当てとか全くやってないけどね)

2010年2月24日水曜日

Page 60: 12 分くらいで知るLuaVM

最後にもしLuaを高速化、最適化したいのであれば、それは重い動作をC関数に落とし込むのが最善です

LuaにはJITや最適化バイトコードの話もありますが、まずは重い処理をC関数にするのが良いです

VMみるのは恐らく、最終手段2010年2月24日水曜日

Page 61: 12 分くらいで知るLuaVM

ご静聴ありがとうございました

2010年2月24日水曜日