From: Tadashi Saito Date: 2008-04-15T12:01:42+09:00 Subject: [ruby-dev:34394] Re: Preparing for 1.8.7-preview1 斎藤と申します。 On Mon, 14 Apr 2008 20:45:26 +0900 "Akinori MUSHA" wrote: >  延び延びになってしまいましたが、ようやく enumerator 関連、 > Enumerable, Array のバックポートが終わりました。 > >  明日の夕方に preview1 を出します。 knuさん、お疲れさまです。 トラッカーの繰り返しになってしまい恐縮ですが、どなたか GC.stress をコミットして頂け ませんでしょうか。 http://rubyforge.org/tracker/index.php?func=detail&aid=19000&group_id=426&atid=22040 スクリプトを書いている人向けというよりも、Cを書いている人向けの機能なので優先度が 一段下がるのは納得なのですが、非常に個人的な理由(拡張ライブラリを書いてる)から 1.8にも入っていると、とてもうれしいです。 内容としても、trunkからほぼ丸写しで済んでportらしい修正もなく、技術的なリスクも比較的 低いと考えます。 トラッカーのWebページでは、なぜか行末が折り返されてしまってパッチが壊れている (メールの notifier だと大丈夫なのに…) ので、メール末尾に、それを訂正してかつ更新したパッチを 再掲します。 > (...) 興味と時間が > あればお願いします。 ということで、気が向いた方がもしいらっしゃったら、よろしくお願いします。 Index: signal.c =================================================================== --- signal.c (revision 16024) +++ signal.c (working copy) @@ -628,6 +628,8 @@ } #endif + extern int ruby_gc_stress; + ruby_gc_stress = 0; rb_bug("Segmentation fault"); } #endif Index: gc.c =================================================================== --- gc.c (revision 16024) +++ gc.c (working copy) @@ -76,6 +76,8 @@ static VALUE nomem_error; static void garbage_collect(); +int ruby_gc_stress = 0; + void rb_memerror() { @@ -89,6 +91,41 @@ rb_exc_raise(nomem_error); } +/* + * call-seq: + * GC.stress => true or false + * + * returns current status of GC stress mode. + */ + +static VALUE +gc_stress_get(self) + VALUE self; +{ + return ruby_gc_stress ? Qtrue : Qfalse; +} + +/* + * call-seq: + * GC.stress = bool => bool + * + * updates GC stress mode. + * + * When GC.stress = true, GC is invoked for all GC opportunity: + * all memory and object allocation. + * + * Since it makes Ruby very slow, it is only for debugging. + */ + +static VALUE +gc_stress_set(self, bool) + VALUE self, bool; +{ + rb_secure(2); + ruby_gc_stress = RTEST(bool); + return bool; +} + void * ruby_xmalloc(size) long size; @@ -101,7 +138,7 @@ if (size == 0) size = 1; malloc_increase += size; - if (malloc_increase > malloc_limit) { + if (ruby_gc_stress || malloc_increase > malloc_limit) { garbage_collect(); } RUBY_CRITICAL(mem = malloc(size)); @@ -141,6 +178,7 @@ if (!ptr) return xmalloc(size); if (size == 0) size = 1; malloc_increase += size; + if (ruby_gc_stress) garbage_collect(); RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { garbage_collect(); @@ -383,7 +421,7 @@ if (during_gc) rb_bug("object allocation during garbage collection phase"); - if (!freelist) garbage_collect(); + if (ruby_gc_stress || !freelist) garbage_collect(); obj = (VALUE)freelist; freelist = freelist->as.free.next; @@ -2037,6 +2075,8 @@ rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0); rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0); rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0); + rb_define_singleton_method(rb_mGC, "stress", gc_stress_get, 0); + rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); rb_mObSpace = rb_define_module("ObjectSpace"); -- 斎藤ただし