[#43284] [Ruby 1.9 - Bug #4456] [Open] Time#strftime で %F 指定子に大きな幅を指定した際の不具合 — tadayoshi funaba <redmine@...>

14 messages 2011/03/02

[#43317] [Ruby 1.9 - Bug #4474][Open] 複数のスレッドからトランザクションに入ろうとした場合のPStoreの挙動 — Masaki Matsushita <redmine@...>

9 messages 2011/03/06

[#43327] [Ruby 1.9 - Feature #4483][Open] PStoreをデフォルトで複数のスレッドから扱えるようにしたい — Masaki Matsushita <redmine@...>

10 messages 2011/03/08

[#43365] [Ruby 1.9 - Bug #4536][Open] 定数参照について1.8と1.9の違い — Yukihiro Matsumoto <matz@...>

11 messages 2011/03/29

[ruby-dev:43304] Re: iseq_compile_each()でのマジックナンバ

From: Yusuke ENDOH <mame@...>
Date: 2011-03-04 19:08:47 UTC
List: ruby-dev #43304
遠藤です。

このメールに気がついてませんでした。


2011年3月5日0:05 nagachika <nagachika00@gmail.com>:
>> というコードがあるのですが、0x4000の意味(用途)がわかりません。
>> vm_throw()ではこの値(ビット)をみていないようなのです。
>> need valueというコメントがあるので、必要っぽい感じなのですが、
>> デバッグ用に使うくらいしか思いつかないのです。
> 確かに使用されていないように見えますね。
> ここの他2箇所(計3箇所)の 0x4000 ビットを立てている所を削って
> make check でテストしてみましたがエラーが増えているようではありませんでした。
> 過去の何かの名残りで今は不要になってしまっているものではないでしょうか?


そう言うのに悩んだときは git log -p とかで過去の記録を見てみると
いいですよ。
このコードが入ったのは r11439 (Merge YARV) で、その時は 0x4000 を
使うコードが確認できます (insns.def の throw) 。そのコードは vm.c
の vm_throw に移り (r12887) 、その後 r16568 で消されています。


commit 956dead48069a07eb1211283ae5b276ef45f6768
Author: mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date:   Sat May 24 06:29:48 2008 +0000

    * compile.c (iseq_set_exception_table, NODE_WHILE, NODE_NEXT): remove
      special handling that decrements sp in CATCH_TYPE_NEXT for NODE_WHILE.

    * vm.c (vm_eval_body), vm_insnhelper.c (vm_throw): remove unused code.


    git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16568
b2dd03c8-39d4-4d8f-98ff-823fe69b080e

diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index bf9ded1..6fb867a 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1204,12 +1204,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
        VALUE *pt = 0;
        int i;
        if (flag != 0) {
-           if (throw_state & 0x4000) {
-               pt = (void *)1;
-           }
-           else {
-               pt = 0;
-           }
+           pt = (void *) 1;
        }
        else {
            if (state == TAG_BREAK) {


えっ、消したの私なんですね。コミットログを見て思い出すと、

- next は引数を取る (next val) ので、スタックを消費する

- しかし、while の中で next に値を与えても捨てられるだけなので、
  スタックの無駄になる

- while の中の next だけ特別扱いしてスタック消費しないようにし
  ていた (0x4000 はスタックを消費する場合のフラグ)

というものだったはず。
でも、なぜこの最適化をやめたのかまでは書いていませんね。ダメダメ。

なぜかというと、この最適化をしているとベリファイア作る上でスタッ
ク長の検証がとても難しくなる問題がわかったんだったと思います。
さらにこの最適化はもともと /* TODO: Dirty Hack!  Fix me */ と書
かれるようなものだったこともあって、ささださんが消していいと言っ
たはず。

# ちなみにこのコメントは今でも iseq_set_exception_table の中に
# 残っていますが、Dirty Hack 自体は消えています。コメントが追い
# ついてない……。


きたざわさんが示された箇所 (NODE_BREAK) でも 0x4000 が関わって
いたんですね。while の返り値が使われる場合 (loopval_popped が 0
の場合) だけ、break の引数をスタックに載せるという最適化だったと
思われます。
でも、loopval_popped が 0 以外になる可能性がコード中から見いだせ
ないので、if (ip->compile_data->loopval_popped == 0) の分岐は意
味がないんじゃないかなーと思います。
当時 (2008/05/24) の IRC のログを見てみたところ、同じことを言っ
てました。

11:13:10 <mame> loopval_popped はもう使われていないのではないか


というわけで、0x4000 関係のコードと loopval_popped 関係のコード
は全部取り除いてよさそうです。

-- 
Yusuke Endoh <mame@tsg.ne.jp>

In This Thread