YARVを読む: diff RHG YARV (2)

なんとなく評価系の大まかな流れがつかめたところで、登場する構造をちゃんと見てみる。ささださんの連載とかぶりそうだけど気にしない。

#define GetISeqVal(obj, tobj) Data_Get_Struct(obj, yarv_iseq_t, tobj)

えっと、iseqは普通の拡張ライブラリオブジェクトと。で、本体がstruct yarv_thread_structね。で、VMもThreadもRDataっと。各構造体は現段階ではよく分からないメンバーが多いので引かない。

あとは、これがどこで初期化されてるかだね。GET_THREADというマクロがあって多用されている。定義を見てみると、カレントスレッドはyarv_thread_t *yarvCurrentThread というグローバル変数に設定されていることが分かる。あ、これがIPAの最終報告会でいってたやつかな。Giant lockで、プロセス内で真の意味で同時に動いてるRubyスレッドは1つだから。グローバル変数でOK?

で、この変数はNULLで初期化されてて、設定されるところを探すとInit_yarvにあった。ここでメインスレッドに対応するyarv_thread_tを生成して、初期VMを作って、VMをスレッドの所属VM(vmメンバー変数)に設定している。VMグローバル変数だな。theYarvVM。

……と思ったら、その後のInit_yarvcoreでもyarvCurrentThreadを設定してる。コメントを見ると"create main thread"と書いてある。するってぇと、最初に設定したスレッドはダミーか。なんでまた、と思って今度はGET_THREADを使っているところを探してみると、PUSH_TAGが改変されててGET_THREADを使ってるんですけど。この辺? yarvCurrentThreadがないとPUSH_TAGもできないから?

あ、これで前回の流し読みでよく分からなかったInit_yarvcoreの後半の意味が分かってきた。やはり静的構造をちゃんと見るべきですね、青木さん。

  • YarvCore::VM.newする
  • 作ったオブジェクト(RData)のポイント先を捨ててしまって、代わりにtheYarvVMを代入
  • theYarvVMのメンバーselfに作ったオブジェクトを代入

やっぱり、ここでRubyのコンテキストでのYarv関連オブジェクトと、C言語レベルの構造体が結びつけられるらしい。今までは仮の設定と言うわけね。

スレッドは、Init_yarvで作ったほうを捨てて、改めてRubyインスタンス化機構を使って作りなおしてる。で、対応する構造体をyarvCurrentThreadに設定。

で、スレッド構造体の初期化はth_init2に書いてありますよ、と。ここを読めばスタックとかの意味も少し分かってくる。

何故仮のthreadが必要だったのかよくわからないけれど、今は放置。あとで読む。

評価中はスレッド構造体のcfpメンバーが頻繁に操作される。これはcontrol frame pointerか。あとは、yarv_control_frame_tの構造について知っとく必要がありそう。次はそっちへ行く予定。