ruby-trunk-changes r45407 - r45440

今日は Symbol GC が導入されました! これまで Symbol は一度確保されると解放されませんでしたが、Ruby スクリプト上で String#to_sym や String#intern で生成した Symbol はその他のオブジェクトのように struct RVALUE のスロットに格納されるオブジェクトになり、 GC の対象になりました。

kazu: r45407 2014-03-25 23:42:36 +0900

拡張ライブラリ pathname の Pathname#join の実装で引数リストの先頭に self を unshift してたのをやめて、最後まで絶対パスとして解決できなかったら先頭に self を加えることにしています。

nobu: r45408 2014-03-25 23:57:18 +0900

r45405 の省略不可能なキーワード引数の SyntaxError 修正の再修正。parser_yylex() で改行を処理するところでキーワード引数のラベルの直後だったら無視せずに改行トークンを返すようにしています。 [ruby-core:61658] [Bug #9669]

naruse: r45409 2014-03-26 01:58:42 +0900

C level backtrace の行番号を取得する fill_lines() で traces のエントリをスキップする条件の間違いを修正しています。

naruse: r45410 2014-03-26 01:58:45 +0900

C level backtrace で実行中のプロセスの実行ファイルのパスを取得するのに(Linux では /proc/self/exe を利用するように r45394 で対応されましたがそれ以外では) dladdr(3) に rb_dump_backtrace_with_lines() という実行中の関数自身のシンボルで取得しようとしていましたが、main() 関数のを渡して取得するように変更しています。 rb_dump_backtrace_with_lines() だと --enable-shared でビルドされてた場合共有ライブラリに含まれている可能性があるからかなと思います。

svn: r45411 2014-03-26 01:58:47 +0900

version.h の日付更新。

naruse: r45412 2014-03-26 03:44:32 +0900

r45410 の追加修正。 main() は公開されていない関数だったので _start() を利用するように再度変更しています。

nobu: r45413 2014-03-26 08:29:44 +0900

lib/rubygem.rb のコメントに書かれていた RubyGems の作者のひとりである Jim Weirich の名前のスペルが間違っていたのを修正しています。 https://github.com/ruby/ruby/pull/577

charliesome: r45414 2014-03-26 08:46:05 +0900

String#gsub で置換する文字列が渡されていて、ブロックつきの呼びだしや置換する結果を Hash で渡していなかった場合には正規表現のマッチで後方参照用の文字列オブジェクトを生成するのをやめるようにしています。https://github.com/ruby/ruby/pull/578 [ruby-core:61682] [Bug #9676]

nobu: r45415 2014-03-26 08:52:18 +0900

r45414 で追加した rb_reg_search0() の宣言位置を internal.h の中で別の re.c の関数と同じところに移動しています。

naruse: r45416 2014-03-26 08:55:39 +0900

C level backtrace を取得する fill_lines() で一度処理したフレームは再度処理しないように lines[i].line に -2 を格納しておくようにしています。だいぶ秘境めいてきました。

naruse: r45417 2014-03-26 08:55:58 +0900

詳細わかりませんが rb_bug() での C level backtrace の表示位置の変更と powerpc64-linux のプラットフォームでの C level backtrace 取得時のデバッグメッセージ追加をしています。CI のデバッグ用だと思います。

naruse: r45418 2014-03-26 09:02:24 +0900

r45412 で現在のプロセスの実行ファイルの取得のために dladdr(3) に _start() を渡すようにしていましたが、直接 _start を関数ポインタとして渡すのではなくて dlopen(3) + dlsym(3) 経由でアドレスを取得して渡すように修正しています。 powerpc64-linux 向けの修正でしょうか。

kanemoto: r45419 2014-03-26 09:13:36 +0900

configure に --disable-pie オプションを追加して位置独立実行形式のバイナリを作らないようにする指定を可能にしています。 linux-eabi というプラットフォーム(EABI は ARM の ABI の一種だそうです)で PIE を有効にするとビルドに失敗するそうで、そのような環境で指定により -pie を落としてコンパイルできるように対応するために追加したそうです。 [ruby-dev:48069] [Feature #9673]

kanemoto: r45420 2014-03-26 09:48:33 +0900

r45419 の ChangeLog エントリにチケットへの参照を追記しています。 [ruby-dev:48069] [Feature #9673]

naruse: r45421 2014-03-26 10:38:05 +0900

C level backtrace 取得のための fill_line() へ curobj_baseaddr という static 変数を介してベースアドレスを渡していたのをやめて、引数に offset を渡して lines[offset].base_addr で取得するようにリファクタリングしています。

naruse: r45422 2014-03-26 10:38:23 +0900

C level backtrace 取得のためデバッグ情報を読む follow_debuglink() で既に open(2) & mmap(2) されていた fd を閉じる時にデバッグ用メッセージを出力するようにしています。

nobu: r45423 2014-03-26 11:20:26 +0900

拡張ライブラリ thread の ConditionVarable と Queue は Marshal.dump でダンプできないように TypeError を発生させる marshal_dump メソッドを定義しています。 [ruby-core:61677] [Bug #9674]

nobu: r45424 2014-03-26 11:20:52 +0900

r45423 の追加修正で marshal_dump メソッドが remove_method で消されても、struct RBasic::klass が 0 の内部的オブジェクトは Marshal.dump でダンプできないようにすることで Queue や ConditionVariable がダンプできないようにしています。 [ruby-core:61677] [Bug #9674]

naruse: r45425 2014-03-26 13:30:43 +0900

C level backtrace 取得の関数 fill_lines() で base_addr と saddr の型を intptr_t から uintptr_t に変更しています。それから不要になっていた(?) syms 引数を削除しています。 あと lines のループを回す順番を反対にしたりしていますがここはよくわからず。

nari: r45426 2014-03-26 13:57:47 +0900

Symbol GC を導入しています。 Ruby では Symbol は内部的に一意な ID という型の数値が与えられてオブジェクトとは別のテーブルで(も)管理されていたため GC の対象にならず、大量の Symbol を生成するとメモリ使用量が増えたまま不要になっても減らないという問題が知られていましたが、String#to_sym などで Ruby のメソッドで生成した Symbol は GC できるようになるようです。
インタプリタが最初から作っている Symbol や C の関数で生成したもの、また SYM2ID() で ID 値が取り出されて C level でその値が格納された(可能性がある)ものは pindown といって GC されないようにしています(Symbol オブジェクトの参照がなくなっても ID が利用されている可能性があるので)が、それ以外の Symbol は参照がなくなったら GC されるようにしています。このために struct RSymbol という構造体とオブジェクト型の T_SYMBOL が追加されています。 GC 可能な Symbol は struct RVALUE のスロットに入るようになるんですね(あたりまえですけど)。 GC されると同じ Symbol でも object_id が別の値になりますが、まあそれはいいだろうってことですね。
また pin down された Symbol は global_symbols.pinned_dsym に登録されて、ここからマークされることで GC されなくなるんですね。てことはスロットは占有したままになるので SYM2ID() で pin down してしまうことはできるだけ避けるようにしたほうがいいんですね。
[ruby-core:61456] [Feature #9634]

nari: r45427 2014-03-26 14:14:51 +0900

r45426 の Symbol GC の修正。 id_type() で戻り値の型にあわせて return 文にキャストを追加しています。

nari: r45428 2014-03-26 14:39:22 +0900

USE_SYMBOL_GC が未定義の時は 1 にするようにしてデフォルトで Symbol GC が有効になるようにしています。

usa: r45429 2014-03-26 14:58:41 +0900

r45426 の Symbol GC の修正。 parse.y に inline 関数があったのですが mswin では inline 関数は static でないといけないということで inline 修飾子を削除しています。

nobu: r45430 2014-03-26 15:34:31 +0900

r45426 の Symbol GC の修正(っていうのは以下省略。バックポート対象じゃないし)。 parse.y の rb_str_dynamic_intern() で文字列のエンコーディングが US-ASCII だったらコピーした文字列を Encoding と紐づけ直す必要がないので処理をスキップするようにしています。なお元の文字列のエンコーディングによらず含まれる文字列が ASCII only だと US-ASCII エンコーディングと紐づけています(という処理を元々 US-ASCII だったら不要なのでスキップしている)。

nobu: r45431 2014-03-26 15:34:33 +0900

同じく rb_str_dynamic_intern() で渡された文字列のエンコーディングが US-ASCII でない時だけ複製を作る必要があるので不要なコピーは作らないようにしています。

nobu: r45432 2014-03-26 15:34:35 +0900

同じく rb_str_dynamic_intern() で複製されるかもしれない str の最適化による GC のマーク漏れの対処方法を変更して RSTRING_PTR() で利用した後に RB_GC_GUARD() を置くようにしています。

nobu: r45433 2014-03-26 15:36:50 +0900

r45431 で dup という変数を削除したのに使っているところが残っていたので str に変更しています。

nobu: r45434 2014-03-26 15:43:02 +0900

rb_str_dynamic_intern() で rb_str_symname_type() の第2引数にビットマスクを渡すべきところを TRUE を渡していたのを修正しています。

naruse: r45435 2014-03-26 16:40:51 +0900

r45417 の powerpc64-linux の時の C level backtrace 取得のデバッグ出力にさらに内容を追加しています。

nobu: r45436 2014-03-26 17:24:09 +0900

Encoding.compatible? の引数に Symbol も受け付けるように enc_capable() で T_SYMBOL の時も真を返すようにしています。

naruse: r45437 2014-03-26 19:59:44 +0900

C level backtrace を取得する fill_lines() で ELF フォーマットの .debug_line セクション、.symtab セクション、.strtab セクションのアドレスを取得したら ELFヘッダのスキャンを止めるようにしていたのをやめています。どうせ strtab と symtab が最後のセグメントだからあんまり意味がないとのこと。

nobu: r45438 2014-03-26 20:14:44 +0900

Symbol オブジェクトから rb_enc_get_index() で encindex を取得するのに対応するため T_SYMBOL の時に struct RSymbol::fstr を取り出す処理を追加しています。 が、次の r45439 で revert されています。

nobu: r45439 2014-03-26 20:30:54 +0900

r45438 の変更を revert してそのかわり parse.y の rb_str_dynamic_intern() で rb_enc_associate() を呼び出して Symbol に Encoding を直接紐づけるようにしています。参照している fstring 経由で Encoding をもつか、直接 Symbol オブジェクトで(インスタンス変数で)持つかという違いですかね。

nari: r45440 2014-03-26 23:19:10 +0900

NEWS ファイルに Symbol GC について追記しています。 また rb_sym2str() という C API の追加についても追記しています。これは SYM2ID() を避けて Symbol から String を得るために追加されたようです。