ruby-trunk-changes r63874 - r63885

今日は MJIT の最適化の再実装や SIGCHLD の処理の追加修正などがありました。

k0kubun: r63874 2018-07-07 23:28:34 +0900

r63863 で revert した r62655 の MJIT での PUSH_TAG() 省略の最適化の一部リトライ。 MJIT が生成するソースコードで reg_cfp->pc の rollback を catch_except_p が偽の時だけにしてたのを常に実施するようにしています。 [ruby-core:87764] [Bug #14892]

k0kubun: r63875 2018-07-07 23:41:03 +0900

r63874 の続き。 insns.def の最適化命令 opt_aset_with と opt_aref_with の実装で MJIT のコード生成時には key を VM スタックに push しないようにしています。 [ruby-core:87764] [Bug #14892]

k0kubun: r63876 2018-07-07 23:55:22 +0900

rubyspec の Process.wait のテストで pid が残ってないかのテストで MJIT 有効時には今は失敗する可能性があるので skip するようにしています。

normal: r63877 2018-07-08 08:59:23 +0900

r63876 でコメントアウトした rubyspec のテストの対応をしてコメントアウトを戻しています。rb_f_exec() で子プロセス(とは限らないか)のプロセスイメージを新しいコマンドに変更する時に mjit_pause() を呼んで MJIT 用の worker 子プロセスを止めてから呼ぶようにしています。 [ruby-core:87846] [Bug #14867]

svn: r63878 2018-07-08 08:59:24 +0900

version.h の日付更新。

normal: r63879 2018-07-08 09:02:27 +0900

恥ずかしながら知らなかったのですが Linux 2.6 以降ではシグナルハンドラで SA_NOCLDWAIT というフラグを使うことができて、これを立てると子プロセスが終了した時に親プロセスで wait しなくてもゾンビプロセスにならないという仕組みがあるそうです。で実は ruby の SIGCHLD のデフォルトのハンドラはこれを使ってた(ということはたぶん昔このフラグを使ってるのを読んだことがあるはずなんだけど気がついてなかった)のですが、これを使うと子プロセス終了時に親プロセスに SIGCHLD が送信されるかどうかは POSIX では未定義で、送信されなくなることもあるようなので、このフラグを使わずに SIGCHLD の処理で同じ挙動をするようにエミュレートさせるようにしているようです。エミュレート内容がこれでいいのかというのはちょっと謎ですが(SA_NOCLDWAIT が指す挙動をちゃんと理解できてないのかも)。

normal: r63880 2018-07-08 10:46:31 +0900

r63879 で追加したテストで Signal.trap で SIGCHLD のハンドラを ensure 節で元に戻してましたが、SIGCHLD がない環境で skip した時も ensure 節は通るのでこの時は無視するようにしています。 [ruby-core:87860] [Bug #14867]

k0kubun: r63881 2018-07-08 11:25:46 +0900

make tbench というターゲットは未使用だったので削除しています。

k0kubun: r63882 2018-07-08 13:12:04 +0900

benchmark/driver.rb で optparse.rb の require 失敗した時のリカバリがたぶん昔の名残りで2度目かどうかのフラグを変数で管理していた(多分昔は redo かループになってたのかな)のですがもう不要なので削除しています。

k0kubun: r63883 2018-07-08 14:52:12 +0900

tool/git-refresh でローカルリポジトリが既に最新版だったら fetch を省略するようにしています。 git describe --tags で対象の tag に紐づいてたら不要なのでスキップするようにしています。

normal: r63884 2018-07-08 16:27:24 +0900

RubyVM::MJIT.resume すると pthread_atfork() が繰り返しフックを登録するためメモリリークが生じていたので、このフックは thread.c の rb_thread_atfork() から呼ばせるようにして MJIT の thread 起動時にセットしないようにしています。

normal: r63885 2018-07-08 16:27:29 +0900

Kernel#sprintf および Time のテストで GC 絡みのオブジェクト解放をチェックするテストで、背後に別の Thread があるとそこから GC が発生して結果が代わってエラーになる可能性があるので、GC.disable にした上で Thread.list に複数の Thread がある状態だと skip するようにしています。