ruby-trunk-changes r43860 - r43885

今日は再帰したネスト構造のオブジェクトの hash 値の計算の修正や psych の 2.0.2 への更新、内部で利用する文字列オブジェクトの fstring 化など最適化や不具合修正が多くありました。 2.1 リリースに向けてかなり加速してきたような感じがありますね。

nobu:r43860 2013-11-27 02:20:16 +0900

Array, Hash, Range, Struct などのネストした構造を持てるクラスの hash メソッドの再帰チェックに rb_exec_recursive_outer() のかわりに rb_exec_recursive_paired() を利用するようにしています。再帰チェックにひっかかった時にネストした構造の最も外側のメソッド呼び出しに戻すのではなく、できるだけ内側までで留めて残りの処理を続行するようにしているのだと思います。
また

a = []
a << a
[a].hash == a.hash

が true になる(無限再帰している構造が同一だと同一のハッシュ値になる)というテストケースを削除しています(実際にはテストは [a].hash ではなくて a.hash との比較になっていました)。おそらく実装上この仕様を保つのが難しいためこれまでは一緒だったのを保証しなくしたのだと思います。

svn:r43861 2013-11-27 02:20:22 +0900

version.h の日付更新。

nobu:r43862 2013-11-27 02:27:01 +0900

str_new4() で共有文字列を作成する時に ObjectSpace.memsize_of で正しいメモリ使用量が返せるように capa もコピーするようにしています。

tenderlove:r43863 2013-11-27 04:48:03 +0900

拡張ライブラリ psych で時刻をパースするための正規表現を修正しています。 タイムゾーン(offset) のあたりの ":" の許容を変更しているようにみえるのですが追加されているテストをみると ":" だけのことでもなさそうです。はて。 https://github.com/tenderlove/psych/issues/171

tenderlove:r43864 2013-11-27 06:41:48 +0900

r43863 に続いて拡張ライブラリ psych の時刻のパース用の正規表現の修正。年に負の数を受けつけるようにしています。 https://github.com/tenderlove/psych/issues/168

tenderlove:r43865 2013-11-27 07:14:34 +0900

拡張ライブラリ psych のバージョンを 2.0.2 に更新して gemspec ファイルも更新しています。

tmm1:r43866 2013-11-27 08:30:25 +0900

VM 命令へのコンパイル時に生成する iseq が保持する String オブジェクトのコピーのかわりに rb_fstring() を用いてできるだけ不要なコピーを行なわないようにしています。 また rb_fstring() で文字列オブジェクト以外が渡された場合の考慮と既に rb_fstring() で生成された共有された fstring が渡されたらそのまま返すようにする処理を追加しています。 [ruby-core:58599] [Bug #9159] [ruby-core:54405]

nobu:r43867 2013-11-27 09:32:37 +0900

SIGSEGV 受信時の挙動のテストで一時ディレクトリに移動して子プロセスを起動して後始末でそのディレクトリを削除することで core ファイルを削除するようにしています。 chkbuild の false error を防ぐためとあるので、chkbuild は core ファイルの存在をチェックしてエラーにするような機能があるのでしょうか。もしかしてこれを backport すると RubyCI の Debian でたまに起きるこのテストの失敗が SEGV として検出されてしまう現象が収まったりするのでしょうか?

tmm1:r43868 2013-11-27 10:42:25 +0900

gc.c の rb_heap_t の構造体メンバ名を used -> page_length, limit -> total_slots と改名しています。

headius:r43869 2013-11-27 12:28:48 +0900

String#<< のテストに Symbol を渡した時に TypeError が発生するテストケースを追加しています。

tmm1:r43870 2013-11-27 14:28:55 +0900

Hash のキーに文字列を渡すと dup+freeze したコピーを利用するようになっていますが、 rb_fstring() (文字列リテラルの時と同じく共有される)を利用するように変更しています。 [ruby-core:57727] [Bug #8998]
これ追加されているテストケースが文字列リテラルによる Hash のキーの object_id を比較しているのですが、既に文字列リテラルによるオブジェクトである時点で同じオブジェクトを返しているので適切なテストケースになっていないような気が…。

tmm1:r43871 2013-11-27 14:39:38 +0900

r43866 で eval に渡したファイル名や ISeq のラベルを fstring にしたことを確認するテストケースを追加しています。 [ruby-core:58599] [Bug #9159]

drbrain:r43872 2013-11-27 14:50:21 +0900

Rinda::RingServer で TupleSpace の take に指定しているクラスが RbObject になっているため同一のプロセスのオブジェクトに対して通知できないので指定なしを意味する nil にして、同一のプロセス内でも通知できるようにしています。 [ruby-core:58626] [Bug #9163]

tmm1:r43873 2013-11-27 15:03:37 +0900

r43870 や r43871 で追加したテストで assert_equal を使っていたところを assert_same を利用するようにしています。自動で object_id つきのメッセージを出してくれる minitest の assertion のようです。

ko1:r43874 2013-11-27 15:09:55 +0900

GC.stat に新たに heap_eden_page_length と heap_tomb_page_length の2つの heap ごとの page 数の項目を追加しています。どうやら GC のテストで GC.stat[:heap_length] を使っていたところが eden heap の page 数のみカウントしないといけなかったためテストが失敗することがあったのを対処するために追加したようです。

ko1:r43875 2013-11-27 15:13:19 +0900

r43874 で追加したデバッグ用 fprintf() が残っていたので if の条件を偽にして出力を抑制しています。

tmm1:r43876 2013-11-27 15:24:37 +0900

r43870 の hash_aset_str() で st_data_t *key の dereference を繰り返し行なっていたところを代入しておいたローカル変数の参照にするようにしています。また r43874 のコンパイラ警告を抑制するため明示的キャストを追加しています。 内容が全く別のものなのでこの場合はコミットを分けて欲しいですね。

tmm1:r43877 2013-11-27 15:57:14 +0900

GC::INTERNAL_CONSTANTS という定数に Hash でメモリ管理に関するサイズなどを格納しておくようにしています。

tmm1:r43878 2013-11-27 16:07:59 +0900

GC のテストで n.times{'a'; nil} のようにしていたところが未使用のリテラルという警告がでるということで nil を消しています。 が、なんとなくこれ 'a' をブロックの戻り値として残さないようにして極力 GC されやすくしているのかなという気もします。なくても参照は残らないと思うので多分大丈夫だと思いますけど。

ko1:r43879 2013-11-27 17:56:48 +0900

gc_mark_stacked_objects() で mark_stack に入っていたオブジェクトが mark 済みでなかったら rb_bug() で異常終了するようにしていたのですが、これを RGENGC_CHECK_MODE が 1以上の時のみ停止するように条件を緩和しています(つまり通常は落ちないように)。
mark_stack って mark してそこからの参照を再帰的に mark するために入れておくスタックだと思うのですが、rb_bug() のメッセージをみると infant (まだ GC を生き延びたことがない)のにマークされていない、というように書かれていてこれはどういうことなんだろう……。最近の GC の進化に記憶が追い付いていません。

a_matsuda:r43880 2013-11-27 18:05:57 +0900

irb の lib/irb/notifier.rb の定数参照の typo を修正しています。 [ruby-dev:47820] [Bug #9165]

a_matsuda:r43881 2013-11-27 21:56:08 +0900

lib/irb/notifier.rb の rdoc 用コメントにも typo があったのを修正しています。また 拡張ライブラリ json の rdoc 用コメントも typo を修正しています。

glass:r43882 2013-11-27 23:57:33 +0900

ruby_atomic.h に ATOMIC_SIZE_CAS() の定義を追加しています。 ATOMIC_CAS() と同じ実装で __atomic_compare_exchange_n() を利用しています。また ATOMIC_CAS() のほうもポインタ変数を使っていたところを対象の型の変数を元の値の格納に直接使うようにリファクタリングしています。なんでポインタを使うように書かれていたんでしょうね。いかにも意味ありげなのでちょっと気になります。 & 演算子でポインタ化することでレジスタでなくてメモリ上に置かれることを強制するためかなぁ。

glass:r43883 2013-11-28 00:13:08 +0900

ATOMIC_{INC, DEC, EXCHANGE} と ATOMIC_SIZE_{INC, DEC, EXCHANGE} で同一の実装になっていたものはまとめて ATOMIC_SIZE_XXX() を ATOMIC_XXX() として #define するようにしています。

svn:r43884 2013-11-28 00:13:12 +0900

version.h の日付更新。

glass:r43885 2013-11-28 01:07:10 +0900

Hash#keys の効率化のために st_keys() という関数を導入して st_table のキーを C の配列に詰めて返させて、これを利用するようにしています。 またこのために st_data と型が compatible か調べるマクロ ST_DATA_COMPATIBLE_P() を導入して st_data と VALUE が compatible が調べてから使うようにしています。 compatible って要するにサイズが同じってことかと思ったのですが(st_keys では特に演算はしなくて代入するだけなので)、sizeof() をチェックするだけでなくて __builtin_types_compatible_p() というビルトイン関数とその結果を利用するための __builtin_choose_expr() を使って実装しています。代入時の暗黙の型変換が未定義の挙動になる可能性があるからかなぁ。