ruby-trunk-changes r61617 - r61640

今日は Stack consistency error の不具合修正、ブロック引数で受け取ったブロックを call メソッドで呼び出した時も Proc オブジェクト化しないようにする最適化などがありました。

nobu: r61617 2018-01-05 23:23:22 +0900

VM 命令へのコンパイル時の unreachable なコードの削除を、jump 命令の飛び先もその元が消えたら連鎖して消すようにしている? という感じに読めました。参照数を減らす数を命令毎に計算しておいて、参照数が結果的に 0 になったら消す、というような全体をみる判定をしている模様。

nobu: r61618 2018-01-05 23:23:23 +0900

while ループの中で return すると Stack Consistency Error が発生するという不具合を修正。こんなのがあったとは。 peephole optimization で jump 先が leave 命令だけだった時に jump を消して leave にするという最適化でVMスタックの深さの調節がうまくいっていなかったとのこと。けどこの最適化部分は最近の変更はされてなかったみたいだけどチケットによると 2.5.0 からみたいで、他の部分の変更が影響しているのかなぁ。手元では2.5.0でも再現しないんだけど……。 [ruby-core:84589] [Bug #14273]

mame: r61619 2018-01-06 00:16:42 +0900

node.h の NEW_DEFN() マクロで不要な引数を受け取らないように変更しています。

svn: r61620 2018-01-06 00:16:43 +0900

version.h の日付更新。

mame: r61621 2018-01-06 00:44:03 +0900

parser.y の method_add_block() に位置情報を渡す引数を追加して、呼び元で nd_loc への代入をしているのをやめるようにしています。

mame: r61622 2018-01-06 01:04:00 +0900

parse.y の yycompile0() で block_append() で既に nd_loc のセットがされているので冗長になっていた代入文を削除。

mame: r61623 2018-01-06 01:04:02 +0900

parse.y で $$->nd_loc への代入などを nd_set_loc() マクロの利用に置き換えています。

ko1: r61624 2018-01-06 02:51:10 +0900

ブロック引数 (&blk) のような記法で受け取ったブロックを blk.call のように Proc#call メソッドで呼び出した時に、Proc オブジェクト化を避けて yield と同等の vm_invoke_block() を利用するようにしています。 r60397 で導入された Proc オブジェクト化の遅延の効果が最終的に blk.call のように呼び出された時もなくならないようにしているのだと思います。2.5 の ブロック引数の Proc オブジェクト化遅延は最終的にブロック呼び出しを blk.call みたいにすると結局 Proc オブジェクト化されるので、高速化のためには block_given? や yield を使わないといけなかったのですが、blk.call を使っても高速なままにできるという、待ち望まれていた最適化だと思います。
call メソッド呼び出しの最適化処理(vm_call_opt_call())で rb_vm_invoke_proc() ではなく vm_invoke_block() を呼ぶようにしているのがミソで、この時 call->receiver に通常の Proc オブジェクトが入ってればそれが呼ばれて、遅延されてるブロック引数だったら cfp から渡されているブロックの呼び出しになるようにしているのだと思います。

naruse: r61625 2018-01-06 04:24:48 +0900

Binding#local_variable_set のテストで再現のため多めのループを回すテストで ARMv8 の環境でタイムアウトしたそうで待ち時間を伸ばしています。

naruse: r61626 2018-01-06 05:36:46 +0900

テスト用のユーティリティ EnvUtil の invoke_rubyタイムアウトした時に、設定されていたタイムアウト時間も表示するようにしています。

naruse: r61627 2018-01-06 05:38:02 +0900

VM 命令へのコンパイルの不要コード削除のテストでやはり再現のためループしているテストでもタイムアウト時間を伸ばしています。

normal: r61631 2018-01-06 05:48:55 +0900

拡張ライブラリ zlib の Zlib::GzipWriter で圧縮処理後のバッファ用の文字列オブジェクトを write の時に頻繁に作りなおしてオブジェクトを使い捨てていたのを、struct RBasic::klass を 0 にして内部的オブジェクトにして Ruby レベルから見えないようにして、内部で極力使いまわすようにしたり、読み切ったら rb_gc_force_recycle() で強制的にバッファを解放させるようにしたりしてメモリ消費量を抑えるようにしています。 [ruby-core:84638] [Feature #14315]

normal: r61632 2018-01-06 06:14:19 +0900

IO.copy_stream で使い終わったバッファ用文字列オブジェクトのサイズを明示的に 0 にして積極的にバッファを解放させるようにしています。ただし fallback 時の実装なので入出力がファイルや socket の時には通らないパスの場合。

kazu: r61633 2018-01-06 13:55:05 +0900

lib/net/http/responses.rb の magic comment frozen_string_literal を true に変更して文字列リテラルを fstring 化するようにしています。

kazu: r61634 2018-01-06 13:55:06 +0900

RFC 8297 で規定された新しい HTTP ステータスコードの 103 Early Hints を標準添付ライブラリ net/http で対応するようにしています。 https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
これ一昨年くらいに CRuby にも最適化のパッチを提供してくださった kazuho さんが提案した RFC ですね。

kazu: r61635 2018-01-06 13:55:07 +0900

標準添付ライブラリ net/http の HTTP ステータスを表すクラスの名前を最新のステータスコード名にあわせて改名しています。たとえば Request Time-Out は Request Timeout になっていたり Request Entity Too Large は Payload Too Large になったり、結構変わってますね。古い名前も互換性のため定数に代入して残しています。 https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml

nobu: r61636 2018-01-06 17:44:17 +0900

r61513 の String#lines などの chomp キーワード引数で delimiter が指定されていた時の対応で delimiter が複数バイトで元の文字列より大きな時の考慮が漏れていてバッファの外にアクセスする可能性があったのを修正しています。 [ruby-core:84552] [Bug #14257]

nobu: r61637 2018-01-06 18:01:02 +0900

Process.spawn などの gid オプションのテストで Process.groups で取得した group が常に利用できるとは限らないみたいで(Open Directory で管理されている時とか?) Etc.getgrgid で id が取得できるものだけ利用するようにしています。

normal: r61638 2018-01-06 18:21:12 +0900

標準添付ライブラリ net/protocol でバッファに使う文字列を String#b で ASCII-8BIT 化するようにしていますが、これは後で revert されています。なんか作業中のものを間違えてコミットしてしまった模様。

normal: r61639 2018-01-06 18:21:35 +0900

標準添付ライブラリ net/ftp で破壊的操作を行う文字列を文字列リテラルで初期化しており、magic comment に frozen_string_literal: true が指定されているので FrozenError が発生するようになっていたので String.new で初期化するように修正しています。2.3 から既に frozen_string_literal: true にされてたのにここまで見過されてたとは。 [ruby-core:84675] [Bug #14323]

normal: r61640 2018-01-06 18:23:43 +0900

r61638 の net/protocol の変更を revert しています。