ひとり勉強会

ひとり楽しく勉強会

YARV

まとめ

はい。おしまいです。YARVソースコード勉強会第一部完です。さて次は何をやろうかなー。。。 Parrotを読む会 JRubyを読む会 とかいう前に、サボりすぎのSICM勉強会をなんとかしないとですねえ。うーん。

ブロッキング

スレッド実行中にI/Oなどシステム関係の操作で処理がブロックするときは、グローバルロックを解除します。YARVのスレッドモデルでは、そうしないと他のスレッドまで一斉に止まってしまうので。これは、ブロックする処理を実装した関数へのポインタを rb_thre…

スレッド切り替え

1個だけ実行するスレッドを、グローバルなMutexのロックという形で明示的に管理しているので、スレッドの切り替えの部分でもロックの取得/解放を明示的に実装することになります。これをやるのが rb_thread_schedule @ thread.c 関数。 void rb_thread_sche…

スレッド初期化

メインスレッド VMのメインスレッドに関する情報は、Init_VM 関数(2006-10-27 - ひとり勉強会)で記録されます。 Thread.new Thread.new による新規スレッド起動の流れを見ていきます。まず、Threadクラスの定義は Init_Thread @ thread.c です。 void Init…

スレッド概要

YARV のスレッドモデルの概略をつかむのには、yarv-dev や ruby-dev のささださんの投稿を参考にしました。 http://www.atdot.net/~ko1/w3ml/w3ml.cgi/yarv-dev/msg/631 [ruby-dev:30202] Re: YARV の thread について 今のところは、model 2、つまり「一つ…

YARVソースコード勉強会 (15)

コンパイラ編(PPT or PDF)に引き続き、VM編のまとめスライドを作りました。 第11回〜第15回まとめ PowerPoint 第11回〜第15回まとめ PDF というわけで、最終回です。今日はマルチスレッド周りのソースを読んでいきます。

まとめ

途中から全然YARVソースコード勉強会じゃなくなってしまいましたが、今日はここまでです。 ささださんが書かれていたとおり、ほんとに簡単にできちゃうんですね。これはかなり楽しかったです。もう少しマジメに作ってみるともっと楽しいかもしれません。今回…

おまけ: Scheme on YARV

これで今日のYARV勉強会はおしまいです。って、これではやけに短くなってしまったので、おまけとして、るびま で触れられていた 本当は、今回何か簡単な言語のコンパイラを作ろうと思っていたのですが、間に合いませんでした。誰か Scheme あたりで挑戦して…

insns.def

insns.defでの命令定義はグループ別にまとまっていて、上から順に 変数の操作 (getlocal, ...) 値の操作 (putnil, ...) スタック操作 (pop, dup, ...) メソッドや別名定義関係 (definemethod, alias, ...) クラス/モジュール定義 (defineclass, ...) メソッ…

YARVソースコード勉強会 (14)

お久しぶりです。週一の勉強会だったはずなのにお久しぶりです。 [YARV] insnhelper.h insns.defはYARVの命令の実装なので、VMの内部状態をいろいろと操作します。VMは前々回見たようなデータ構造で表現されてるわけですが、これをもう少し抽象化して、簡潔…

まとめ

しばらく書いてなかったらひとり勉強会の書き方を忘れています(あせ。なんか変な感じ。 次回は、insns.def の内容を面白そうなところをつまみ食いしながら一気に眺めてみようと思います。あと読んでみたいのは、スレッド周りの実装くらいでしょうか。という…

th_eval_body:例外処理

改めて話を戻して、例外処理について。raise〜rescueやthrow〜catchの他にも、break/redo/next, returnなども同じ仕組みを使って実装されています。この辺りの処理は th_eval_body にまとまっています。基本的な流れとしては… exception_handler: cont_pc = …

th_eval_body:実行

th_set_top_stack で制御フレームの設定が終わったら、いよいよ実行開始。th_eval_body 関数です。 VALUE th_eval_body(yarv_thread_t *th) { ... TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == 0) { vm_loop_start: result = th_eval(th, initial); if ((s…

YARVソースコード勉強会 (13)

一月ぶりのYARV勉強会になってしまいました。今日のリビジョンは r11982 です。いつのまにか yarv_iseq_t が rb_iseq_t になったり、yarv_control_frame_t が rb_control_frame_t になってました。おおお。

まとめ

今日は、YARV仮想マシンの実行時のデータ構造についてと、実際にコードの実行に移るまでのそのセットアップについて見てみました。次回は、実際に仮想マシン語を実行する関数 th_eval_body の方に行く予定です。

実行開始

初期化後、Rubyソースのコンパイルが行われて、コンパイル結果の命令列データが yarvcore_eval_iseq 関数に渡されます。ここがVMによる実行の開始点です。 static VALUE yarvcore_eval_iseq(VALUE iseq) { return yarv_th_eval(GET_THREAD(), iseq); } 指定…

データ構造とその初期化

VM まず、YARV の仮想マシンを表すデータ構造があります。yarvcore.h で定義されている yarv_vm_t 構造体です。 typedef struct yarv_vm_struct { VALUE self; ...略... struct yarv_thread_struct *main_thread; struct yarv_thread_struct *running_thread…

YARV ソースコード勉強会 (12)

最近曜日の感覚がおかしくなってきた hzkr です。今日は、YARV の仮想マシンの実装の入り口をのぞきはじめます。

まとめ

というわけで、これでコンパイル処理は完成です。次回からはVMの実行部のコード読みに移ります。ではではー。

iseq_translate_direct_threaded_code @ compile.c

いよいよステップ5です。YARVの命令処理は「ダイレクトスレッデッドコード」という方式で高速化されています。これについては YARV Maniacs 【第 3 回】 が詳しくてしかもわかりやすいです。それまで他の解説読んでもスレッデッドコードの意味がわからなく…

set_optargs_table @ compile.c

あれれ、コンパイルのところで見落としてました。メソッドのデフォルト引数は、こういう風にコンパイルされるみたいです。 /* * set optional argument table * def foo(a, b=expr1, c=expr2) * => * b: * expr1 * c: * expr2 */ 該当コードはiseq_compile→N…

set_exception_table @ compile.c

次は、set_sequenceで計算したラベルの位置情報を使って、例外ハンドラのテーブルを構築します。コンパイル時に「このラベルからこのラベルの間で例外が発生したら・・・」式のテーブルを作ってあったので、これを単純に、ラベル情報からアドレス情報を取得…

set_sequence @ compile.c

では、ステップ4に進みます。 ここまでのステップで、Ruby の構文木が、命令 (struct INST) とラベル (struct LABEL) のリンクリストへと変換されました。リンクリストのままだと直接実行するにはまだ向かないので、次は、これをYARVの仮想マシン語のバイト…

特化命令(続)

その前に、前回のささださんにコメントいただいた点について、まとめます。YARV Maniacs 第9回 での解説に加えて、現在ではsendメソッドの特化機能が追加されているそうです。 id = :method ... obj.send(id, args) という記述を obj.method(args) と書いた…

YARV ソースコード勉強会 (11)

遊びすぎで気づいたら金曜日と土曜日と日曜日が終わってました。。。今回は、YARVのコンパイルステップ4と5を読みます。 step 4: 命令のリンクリストから、バイトコード(ワードコード)列への変換 step 5: スレッデッドコードのための準備

まとめ

今日はYARVの最適化フェーズについてでした。 ピープホール最適化 特化命令 (オペランド融合) (命令融合) (スタックキャッシング) 専用命令を新しく作る系の最適化に関しては、定義ファイルから新しい命令を自動生成という形になっているのが面白いなーと思…

set_sequence_stackcaching

YARV Maniacs【第8回】 によると「性能上の問題から、現時点では有効にできないようにしてあります」とのことです。一応ソースだけ読んでみました。スタックの先頭付近最大2個分だけ特別な領域(AレジスタとBレジスタ)に持っておいて、スタック操作命令の…

iseq_insns_unification

命令融合。こちらも同じく現在はOFFになってるみたいです。一応ソースだけ読んでみました。さっき見たオペランド融合は、よくある「命令+オペランド」の組を1個の専用融合命令に置き換えてしまう最適化でした。こっちの命令融合というのは、よく連続する命…

insn_operands_unification

オペランド融合。この最適化は現在はOFFになってるみたいです。一応ソースだけ読んでみました。この関数は、ビルド時に定義ファイル"opt_operand.def"から自動生成されます。(自動生成スクリプトは"tool/insns2vm.rb"。)定義ファイルの中身はこんな感じで…

iseq_specialized_instruction

こちらについては YARV Maniacs 【第9回】 で丸々1回をさいて解説されています。引用させていただくと、 すでに述べたように「1 + 2」のようなプログラムは Ruby では「1.+(2)」と解釈されますが、コンパイル時にチェックして、 呼び出すメソッドが "+" 引…