MRUBYVMを調べてみた話MRUBYVMを調べてみた話
kishima
⾃⼰紹介⾃⼰紹介
kishima
お仕事
転職前:テレビ、⾞載通信装置などの組み込
みソフト研究開発等
現在:あるIoTサービスのデバイス開発、運
⽤、障害対応など何でも
データ解析で最近Rubyを使う機会増えた(増
やした)
趣味
mruby、mruby/c、電⼦⼯作、技術同⼈誌執筆
VMを調べてみるメリット
C⾔語拡張を書くときの基礎知識
未知の環境への⾃前でポーティングするときの
基礎知識
純粋に興味深い
CRubyよりは読みやすいと思う
MRUBYとはMRUBYとは
ISO/IEC	30170:2012をカバーする軽量なRuby実装
PC向けに限らず組込みソフトも想定したアプリ
ケーションへの組込みを想定
mrubyの仕組み
mrbc(コンパイラ)の部分はmgemとして分離されて
いる。	VMの部分がコアとして提供されている。
バイナリデータ?
mrubyではバイトコードにコンパイルした中間⽣成
物を⼊⼒としてmrubyVMを実⾏できる。
バイトコードファイルの構造
サンプルコード
def func1
p local_variables
var2=1
end
var1=1
func1
p local_variables
バイトコードに変換した結果バイトコードに変換した結果$ xxd code/bytecode_format.mrb
00000000: 5249 5445 3030 3035 9651 0000 00e8 4d41 RITE0005.Q..
00000010: 545a 3030 3030 4952 4550 0000 00a3 3030 TZ0000IREP..
00000020: 3032 0000 00b4 0002 0005 0001 0000 001f 02..........
00000030: 6102 5603 005d 0200 0701 1002 2e02 0000 a.V..]......
00000040: 1002 1003 2e03 0100 2e02 0201 3702 6700 ............
00000050: 0000 0000 0000 0300 0566 756e 6331 0000 .........fun
00000060: 0f6c 6f63 616c 5f76 6172 6961 626c 6573 .local_varia
00000070: 0000 0170 0000 0000 8c00 0300 0600 0000 ...p........
00000080: 0000 1700 3300 0000 1003 1004 2e04 0000 ....3.......
00000090: 2e03 0101 0703 0102 0337 0300 0000 0000 .........7..
000000a0: 0000 0200 0f6c 6f63 616c 5f76 6172 6961 .....local_v
000000b0: 626c 6573 0000 0170 004c 5641 5200 0000 bles...p.LVA
000000c0: 2700 0000 0300 0476 6172 3100 0126 0004 '......var1.
000000d0: 7661 7232 0000 0001 0001 0001 0002 0002 var2........
mrbc	--verbose	の結果
mruby内部でのバイトコード情報の持ち⽅
mrb_irep構造体
RProc構造体
struct RProc {
MRB_OBJECT_HEADER;
union {
mrb_irep *irep;
mrb_func_t func;
} body;
struct RProc *upper;
union {
struct RClass *target_class;
struct REnv *env;
} e;
};
mrubyの全ての情報を持っているmrb_state構造体
バイトコードの実⾏
バイトコード実⾏までの流れ
VMのメインループVMのメインループ
mrb_vm_exec()
MRB_TRY(&c_jmp) {
INIT_DISPATCH {
CASE(OP_XXX, ***) {
/* do something */
NEXT;
}
***
繰 返
}
}
VMのメインループ(マクロを展開)
if (setjmp((&c_jmp)->impl) == 0) {
/* INIT_DISPATCH */
insn=(*pc);
goto *optable[insn]
return mrb_nil_value();
{
/* CASE */
L_OP_XXX:
pc0=pc++;
FETCH_***();
L_OP_XXX_BODY:
{
/* do something */
/* NEXT */
insn=(*pc);
バイトコードの読み込み⽅
まとめまとめ
慣れると気軽に⾊々な環境に持っていける(よう
な気がしてきた)ので、どんどん活⽤してみるよ
う
Thank	you

mruby VM を調べてみた話