Yokohama.rb 第0回 で ytljit のソース読み

@dan5ya さんの呼びかけで立ち上げられた Yokohama.rb の第0回の集りに参加しました。総勢 23 人? の参加者でとても盛況でした。

  • 声に出して読みたい「メタプログラミング Ruby
  • Rails3 と MongoDB で英語学習 Web サービスを作る
  • Puppet の話(といいつつ Chef という競合の話だったみたい)

と大まかに3つのセッションが立ちました。

しかしわたしは Puppet の卓にもぐり込ませて頂いてひとり ytljit のコードリーディングをしていました。ぼっち Hack。ひとりで何かするのも OK と思いましたが、せっかくだからもうちょっと絡んでおかないともったいないかなーと思いました。なので後半は Puppet 組の雑談にちょっと混ぜてもらったり。

ytljit は id:miura1729 さんが手がけてらっしゃる Ruby1.9VM からネイティブコードを変換するプロジェクトです。Ruby で(一部 C の拡張ライブラリ)書かれています。文章にしようとしてみると最終的にどういうことをするものになるのか自分がよく理解していないのがわかります。今のところ、Rubyアセンブラを書けてネイティブコードを生成して実行できるライブラリ、という程度の理解です。

とりあえず GitHub の ytljit プロジェクトの wiki に置いてある文章を読んでから、C の拡張ライブラリで実装されているメソッド群を調査しました。

http://github.com/miura1729/ytljit/wiki/

読みながら書いておいたメモを未整理ですが残しておきます。

  • codespace.c を読む。CodeSpace クラス。
    • メモリチャンクの管理と権限の付与が主な仕事
  • ytljit.c を読む
    • YTLJit.address_of #=> C の関数のアドレスを取得
    • Object.method_address_of #=> メソッドの C の実体(関数)のアドレスを返す)
      • Module#method_address_of でいいような気がするのだけどなぜこうなってるのだろう?
    • YTLJit.memref #=> Intger で渡されたアドレスの 8bit の値(0-255)を返す
    • Binding#to_a #=> ローカル変数の内容の配列を返している。
      • しかしメソッドコールをネストしても最も内側の環境のぶんしか取れない。コードを読むと呼び元の情報も配列に入れて返しているはずのようなのに。ここは CRuby 本体のソースを追わないといけないのでまだちゃんと読んでいません。 [追記]ネストしているブロックでのローカル変数とダイナミック変数の中身が配列になっていて、メソッド呼び出しはまたいでいませんでした。勘違い。[/追記]
    • Binding#variables #=> その Bindings のローカル変数名を取り出す。local_variables と返すものがちょっと違うみたい。[追記]Binding#to_a と同じくブロックのネストに対応して配列の配列で返しています。つまり Binding#to_a と組み合わせるとどの変数の値が何になってるかがわかる上に、ブロックのダイナミック変数で外の変数が隠されているとかいうことも(VM内部のことを多少知らないといけませんが)わかるようになっています。[/追記]
    • Object#instance_var_address_of(:@var) でインスタンス変数の値を取れる
    • Proc#to_iseq #=> Proc -> InstructionSequence
    • ValueSpace #=> CodeSpace のデータ版
  • ディレクトリ構成がちょっと標準的でなくて require や -I オプションの指定が面倒だったので、ディレクトリ構成を変更してみた
    • ytljit.c -> ytljit_ext.c にして Init_ytljit() -> Init_ytljit_ext()
    • lib の下を1階層上に( lib/ytljit/ytljit.rb -> lib/ytljit.rb )
    • test/ のテストを実行するための Rakefile を作ってみた

ディレクトリ構成の変更など手元で加えた変更は今度 GitHub で fork してコミットしてみます。