今日もメソッド呼び出し処理まわりの高速化がたくさん入りました。また Net::IMAP の機能追加と mingw での並列ビルド失敗の対策などがありました。
ko1:r37228 2012-10-17 02:07:23 +0900
インラインキャッシュの構造体にあった、インスタンス変数の setter/getter のインデックスを rb_call_info_t に移動しています。 opt_pc と union で同居させています。 インスタンス変数は内部的には配列で保持されていて、名前とインデックスの対応をクラスが持つように(1.9 以降)なっているため、再定義されていなければ*1インデックスだけ記憶しておけば内容を同定できます。
ko1:r37229 2012-10-17 05:30:17 +0900
vm_invoke_block() において vm_caller_setup_args() を呼ぶのは flags に VM_CALL_ARGS_SPLAT が立っている時だけにしています。 vm_caller_setup_args() は VM_CALL_ARGS_BLOCKARG のビットフラグに対応した処理もありますが vm_inboke_block() は yield 文に対応する命令の invokeblock からのみ呼ばれるので、文法上ブロック引数を受け取れないのでありえないですね。 なお最近の CPU は分岐予測や reorder が賢いので UNLIKELY() みたいなので手動でヒントをつけるとかえって遅くなる時もあると kosaki さんに教わりましたが、ここの UNLIKELY() はどうなんでしょうか。
関係ないですけど yield にブロック引数を受け取れるようにして Proc#call と同等にしたいなあと思っていたことを思い出したので、その時にはここの条件も修正しましょう。
ko1:r37231 2012-10-17 06:20:11 +0900
vm_call_iseq_setup_2() という ISeq 型(ruby で定義された)メソッドの呼び出し時のコントロールフレーム操作を、通常時と tailcall (末尾呼び出し)時で別の関数に分けるリファクタリングです。ただし tailcall タイプの時に RUBY_VM_CHECK_INTS() の呼び出しが追加されています。末尾再帰した場合に Thread が切り替わらず割り込みできない状態になる可能性があったからだそうです。
tenderlove:r37232 2012-10-17 06:33:59 +0900
Hash#dup した時に Hash の内部的実装である st_hash のイテレータを使って順に要素をコピーしていたのを st_copy() 関数を使ってコピーするようにして高速化を図っています。 ただチケットの報告をみると Set の動作に影響があったようです。 [ruby-core:48009] [Bug #7166]
ko1:r37233 2012-10-17 06:49:18 +0900
vm_call_method() の最後に RUBY_VM_CHECK_INTS() を呼ぶのを削除しています。さっきもでてきましたが RUBY_VM_CHECK_INTS() というのは、タイマー割り込み(同じ Thread が動き続けていたら一定時間で切り替わるようにフラグが立てられる)や別の Thread からの割り込み(例外や Thread.kill)、シグナル(メインスレッドのみ)がないかチェックして、必要ならスレッドの切り替えを実行する処理がまとめられたマクロです。ここは VM からメソッドの呼び出しをした時にスレッド切り替えポイントにならなくなったということです。
ko1:r37234 2012-10-17 08:03:54 +0900
r36470 のあたりで追加された Thread.control_interrupt の内部で interrupt_mask を操作した後に RUBY_VM_CHECK_INTS() を読んで割り込みチェックするようにしています。 mask で pending されていた割り込みがあるかもしれないからそれをチェックしているんでしょう。
ko1:r37235 2012-10-17 08:38:58 +0900
ダブルクオートの文字列に #{} で式を埋め込む記法を使うと、リテラルですが命令は複数の文字列を作って連結するような動きになるのですが、この時部分文字列のリテラルの部分を putstring で VM のスタックに積んでいたのを putobject で積むようにしています。 putstring はコピーを生成しますが putobject はオペランドをそのまま積むのでオブジェクトの生成数を抑えることができます。 "foo#{bar}baz" のような文字列があった時に "baz" の部分を独立したオブジェクトとして Ruby スクリプト側から取り出すことはできないので*2内容を変更される恐れもないのでコピーは不要ということのようです。
shugo:r37237 2012-10-17 10:50:53 +0900
OPT_INLINE_METHOD_CACHE を 0 にしてインラインキャッシュを無効にした(デバッグ用)時に method_entry の代入先メンバ名が間違っていてコンパイルが通らなかったのを修正しています。
usa:r37238 2012-10-17 11:06:34 +0900
r37232 で Hash#dup の実装を変更した影響を示すテストを追加しています。 dup したものと == で比較して一致しなくなるみたいですね。
shugo:r37239 2012-10-17 12:55:35 +0900
r37237 の ChangeLog エントリのインデントをタブを使うように修正。
shugo:r37240 2012-10-17 15:18:14 +0900
Net::IMAP に対応するレスポンスを追加しています。 IMAP の仕様がわからないので詳しい内容はチケット等を見ていただくとして、message/delivery-status ([ruby-core:47920] [Bug #7146])、message/rfc822 attachments ([ruby-core:47921] [Bug #7147])、(BODY ("MIXED")) ([ruby-core:47951] [Bug #7153]) の対応を追加しているそうです。
shugo:r37241 2012-10-17 15:30:29 +0900
r37240 の ChangeLog にパッチの作者の名前を追記しています。
nobu:r37242 2012-10-17 15:33:14 +0900
configure のオプション --with-opt-dir に $PATH_SEPARATOR で区切って複数のパスを渡せるようになっています。おおーこれたまに欲しくなることがあったんですよねー。 PATH_SEPARATOR は多分 Linux や Mac OS X や *BSD だと ":" で Windows だと ";" ではないかと思われます。 [ruby-core:47868] [Bug #7120]
ko1:r37243 2012-10-17 16:12:40 +0900
method_missing の実装の変更です。メソッドが見付からなかった時に method_missing を rb_funcall2() で ruby のメソッド呼び出しの機構を使って読んでいたのを vm_call_method() 関数を直接使って rb_call_info_t のキャッシュが効くようにしています。このため rb_call_info_t の union で同居させているメンバ(aux) に missing_reason が追加されています。
ko1:r37244 2012-10-17 16:24:52 +0900
r37228 のインスタンス変数アクセスのために rb_call_info_t::aux::index を追加しましたが index を使うべきところで(union で同居している) opt_pc を使ってしまっていたところがあったのを修正しています。
ko1:r37245 2012-10-17 16:26:58 +0900
method_missing の呼び出しのベンチマークを追加しています。
shirosaki:r37246 2012-10-17 21:20:57 +0900
mingw 環境で make に -j オプションを渡して並列ビルドさせると ruby.exe と rubyw.exe を同時にリンクしようとした場合に失敗するそうなので、 ext/extmk.rb で ruby.exe と rubyw.exe を順にビルドするように Makefile を生成するようにしています。 [ruby-core:48007] [Bug #7165]