From: Kazuki Tsujimoto Date: 2011-06-26T16:19:13+09:00 Subject: [ruby-dev:43910] [Ruby 1.9 - Bug #4926] --gc-stress付きtest/ruby/enc/test_emoji.rbが失敗する Issue #4926 has been updated by Kazuki Tsujimoto. =begin 辻本です。 すみません、vm_clear_all_inline_method_cacheの動きについては勘違いしていました。 ちなみに、ポストしたパッチはキャッシュヒット率を向上させる面もあるので 別途取り込みを検討していただければと思います。 現在の実装では、以下のコードでのm呼び出しによる@ivへのアクセスはいずれもキャッシュミスしますが、 パッチを当てると初回のo0.m以外はキャッシュヒットするようになります。 class C def initialize @iv = 0 end def m @iv end end o0 = C.new o1 = C.new; class <>. (全ログは長いので添付します。) この時の流れは以下の通りです。 (1) vm_setivarにてic->ic_classにRBASIC(obj)->klass(Emoji::TestDoCoMoオブジェクトの特異クラス)が代入される。 (2) 1.の特異クラスがGCで解放される。 (3) Emoji::TestKDDIオブジェクトの特異クラスが1.の特異クラスと同じアドレスで作成される。 (4) icのindexとklassのindexが不一致を起こしてインスタンス変数の参照に失敗する。 ivar_get/rb_ivar_setではRBASIC(obj)->klassではなくrb_obj_class(obj)を使ってIV_INDEX_TBLを扱っており、 そちらに揃えれば問題は起きなくなります。以下のパッチでどうでしょうか。 diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 366ac4a..3736055 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1259,7 +1259,7 @@ vm_getivar(VALUE obj, ID id, IC ic) #if USE_IC_FOR_IVAR if (TYPE(obj) == T_OBJECT) { VALUE val = Qundef; - VALUE klass = RBASIC(obj)->klass; + VALUE klass = rb_obj_class(obj); if (ic->ic_class == klass) { long index = ic->ic_value.index; @@ -1311,7 +1311,7 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) rb_check_frozen(obj); if (TYPE(obj) == T_OBJECT) { - VALUE klass = RBASIC(obj)->klass; + VALUE klass = rb_obj_class(obj); st_data_t index; if (ic->ic_class == klass) { =end -- http://redmine.ruby-lang.org